Spaces:
Runtime error
Runtime error
File size: 8,869 Bytes
d03d74d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | # Vault - Development Guide
**Generated:** 2026-02-11
**Node.js:** 20+
**Package Manager:** npm
---
## Quick Start
### Prerequisites
- Node.js 20+ installed
- npm or yarn package manager
- Supabase account (for database)
- Google Cloud project (for OAuth + YouTube API)
- Inngest account (for background jobs)
- Upstash account (for Redis caching)
### Installation
```bash
# Clone the repository
git clone <repository-url>
cd vault
# Install dependencies
npm install
# Copy environment variables
cp .env.example .env.local
# Edit .env.local with your credentials
```
### Development Server
```bash
# Start Next.js development server with Turbopack
npm run dev
# In a separate terminal, start Inngest dev server
npx inngest-cli dev
# Open http://localhost:3000
```
---
## Environment Variables
### Required Variables
```bash
# Database (Supabase Postgres)
DATABASE_URL=postgresql://...@aws-0-us-east-1.pooler.supabase.com:6543/postgres
DIRECT_URL=postgresql://...@aws-0-us-east-1.pooler.supabase.com:5432/postgres
# Authentication
BETTER_AUTH_SECRET=your-secret-key-min-32-chars
BETTER_AUTH_URL=http://localhost:3000
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# Inngest
INNGEST_EVENT_KEY=your-event-key
INNGEST_SIGNING_KEY=your-signing-key
# Supabase Storage
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
# Redis (Upstash)
UPSTASH_REDIS_REST_URL=https://your-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token
# AI Vision
GEMINI_API_KEY=your-gemini-api-key
HUGGINGFACE_API_KEY=your-hf-api-key
VISION_PROVIDER=gemini # or 'huggingface'
# Marketplaces
AMAZON_ACCESS_KEY=your-amazon-access-key
AMAZON_SECRET_KEY=your-amazon-secret-key
AMAZON_AFFILIATE_TAG=your-affiliate-tag
EBAY_APP_ID=your-ebay-app-id
EBAY_CERT_ID=your-ebay-cert-id
EBAY_CAMPAIGN_ID=your-campaign-id
ETSY_API_KEY=your-etsy-api-key
# Monitoring
SENTRY_ORG=your-sentry-org
SENTRY_PROJECT=your-sentry-project
# Admin
ADMIN_EMAILS=admin@example.com,admin2@example.com
```
### Optional Variables
```bash
# CI/CD
CI=false # Set to true in CI environments
# Development
NODE_ENV=development
```
---
## Database Setup
### Drizzle ORM
Database schema is defined in [`src/lib/db/schema.ts`](../src/lib/db/schema.ts).
### Migrations
```bash
# Generate migration from schema changes
npx drizzle-kit generate
# Run migrations
npx drizzle-kit migrate
# Push schema directly (development)
npx drizzle-kit push
# Open Drizzle Studio
npx drizzle-kit studio
```
### Supabase Setup
1. Create a new Supabase project
2. Get connection strings from Project Settings > Database
3. Create storage bucket named `detected-objects` for thumbnails
4. Run migrations against the database
---
## Testing
### Test Framework
Vitest with React Testing Library.
```bash
# Run all tests
npm run test
# Run tests in watch mode
npx vitest
# Run tests with coverage
npx vitest --coverage
```
### Test Structure
Tests are co-located with source files:
```
src/
βββ features/
β βββ vault/
β βββ services/
β β βββ vault.service.ts
β β βββ __tests__/
β β βββ vault.service.test.ts
β βββ components/
β βββ __tests__/
β βββ vault-grid.test.tsx
```
### Writing Tests
```typescript
// Service test example
import { describe, it, expect, vi } from 'vitest';
import { VaultService } from '../vault.service';
describe('VaultService', () => {
it('should return vault for valid creator slug', async () => {
const vault = await VaultService.getCreatorVault('test-creator');
expect(vault).toBeDefined();
expect(vault?.channel.channelName).toBe('Test Creator');
});
});
```
```typescript
// Component test example
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { ProductCard } from '../product-card';
describe('ProductCard', () => {
it('should render product name', () => {
render(<ProductCard {...mockProps} />);
expect(screen.getByText('Test Product')).toBeInTheDocument();
});
});
```
---
## Code Quality
### Linting
ESLint with Next.js recommended config.
```bash
# Run linter
npm run lint
# Fix linting issues
npm run lint -- --fix
```
### Pre-commit Hooks
Husky runs lint-staged on commit:
```json
{
"lint-staged": {
"*.{js,jsx,ts,tsx,mjs}": [
"eslint --fix"
]
}
}
```
### TypeScript
Strict mode enabled. Build will fail on type errors (configurable).
```bash
# Type check
npx tsc --noEmit
```
---
## Deployment
### Architecture
- **Frontend:** Vercel (Edge/Serverless)
- **Background Workers:** Railway (Docker containers)
- **Database:** Supabase (Managed Postgres)
- **Cache:** Upstash Redis
- **Workflows:** Inngest Cloud
### Vercel Deployment
1. Connect repository to Vercel
2. Configure environment variables
3. Deploy on push to main
```bash
# Manual deployment
npx vercel deploy --prod
```
### Railway Deployment
1. Connect repository to Railway
2. Configure environment variables
3. Set up Inngest worker service
```bash
# Manual deployment
npx @railway/cli up --detach --project <project-id>
```
### CI/CD Pipeline
GitHub Actions workflow: [`.github/workflows/deploy.yml`](../.github/workflows/deploy.yml)
**Build & Test Job:**
- Runs on every push and PR
- Installs dependencies
- Runs lint
- Runs tests
- Builds application
**Deploy Job:**
- Runs on push to main
- Deploys to Vercel
- Deploys to Railway
---
## Development Workflow
### Branch Strategy
```
main
βββ develop
β βββ feature/xyz
β βββ fix/abc
β βββ refactor/def
```
### Commit Convention
```
type(scope): description
Types: feat, fix, refactor, docs, test, chore
```
### Pull Request Process
1. Create feature branch from `develop`
2. Make changes and write tests
3. Run lint and tests locally
4. Create PR to `develop`
5. CI must pass before merge
6. Squash merge to `develop`
7. Periodic releases from `develop` to `main`
---
## Debugging
### Local Debugging
```typescript
// Console logging with context
console.log('[VaultService] Fetching vault for slug:', creatorSlug);
// Sentry capture for investigation
Sentry.captureException(error, {
tags: { component: 'VaultGrid', action: 'fetch' },
extra: { creatorSlug },
});
```
### Inngest Debugging
1. Open Inngest Dev Server UI at `http://localhost:8288`
2. View function runs, events, and errors
3. Replay failed functions
4. Inspect step outputs
### Database Debugging
```bash
# Open Drizzle Studio
npx drizzle-kit studio
# Direct SQL query
psql $DATABASE_URL -c "SELECT * FROM detected_objects LIMIT 10;"
```
---
## Common Tasks
### Add a New Feature Module
1. Create directory in `src/features/`
2. Add subdirectories: `actions/`, `components/`, `services/`, `types/`
3. Create server actions with `'use server'`
4. Create components with `'use client'` where needed
5. Add types in `types/`
6. Write tests in `__tests__/`
### Add a New Inngest Function
1. Create file in `src/inngest/functions/`
2. Define event interface
3. Create function with `inngest.createFunction()`
4. Register in `src/app/api/inngest/route.ts`
5. Trigger from server action or other function
### Add a New API Route
1. Create directory in `src/app/api/`
2. Create `route.ts` file
3. Export HTTP method handlers (GET, POST, etc.)
4. Add authentication/authorization as needed
### Add a New Page
1. Create directory in `src/app/`
2. Create `page.tsx` file
3. For dynamic routes, use `[param]/page.tsx`
4. Add metadata export for SEO
5. Use SSR for public pages, client components for dashboards
---
## Troubleshooting
### Common Issues
**Database Connection Errors**
- Verify DATABASE_URL and DIRECT_URL are correct
- Check Supabase project is not paused
- Ensure SSL is required (`ssl: 'require'`)
**Inngest Functions Not Running**
- Verify INNGEST_EVENT_KEY and INNGEST_SIGNING_KEY
- Check Inngest dev server is running locally
- Verify function is registered in API route
**YouTube API Quota Exceeded**
- Check Google Cloud Console for quota usage
- Request quota increase if needed
- Implement caching to reduce API calls
**Marketplace API Rate Limits**
- Check Redis cache is working
- Implement backoff strategies
- Consider upgrading API tiers
### Getting Help
1. Check existing documentation
2. Search GitHub issues
3. Review Inngest dashboard for errors
4. Check Sentry for error details
---
## Related Documentation
- [Project Overview](./project-overview.md) - Architecture and features
- [Source Tree](./source-tree.md) - File structure
- [Data Models](./data-models.md) - Database schema
- [API Contracts](./api-contracts.md) - Endpoints and actions
- [Inngest Workflows](./inngest-workflows.md) - Background jobs
|