Development Guide
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Node.js | 20+ | Runtime |
| pnpm | 9+ | Package manager |
| PostgreSQL | 18 | Database |
| Redis | 7+ | Queue and cache |
Local Setup
1. Install Dependencies
bash
pnpm install2. Configure Environment
bash
cp env.example .envFill in the required variables. At minimum for local development:
DATABASE_URL— PostgreSQL connection stringBETTER_AUTH_SECRET— Generate withopenssl rand -base64 32BETTER_AUTH_URL—http://localhost:3000GOOGLE_APPLICATION_CREDENTIALS— Path to Vertex AI service account keyGOOGLE_VERTEX_PROJECT— GCP project IDGOOGLE_VERTEX_LOCATION—global
3. Database
bash
# Apply schema
npx prisma db push
# Generate client
npx prisma generate
# Seed data
npx prisma db seedTo seed an admin account, set ADMIN_EMAIL and ADMIN_PASSWORD in .env.
4. Start Development Servers
bash
# Terminal 1: Web server (http://localhost:3031)
pnpm dev
# Terminal 2: All workers (reading, insights, translation, question-insights)
pnpm workers
# Terminal 3: Telegram bot (optional)
pnpm telegram-botOr start individual workers:
bash
pnpm worker # Tarot reading worker
pnpm insights-worker # Guidance/journey worker
pnpm translation-worker # Blog translation worker
pnpm question-insights-worker # Question insights workerCoding Conventions
TypeScript
- No
any— Strict typing throughout - Types over interfaces — Use
type TName(nointerface) - Inline props — Component props are defined inline, not extracted
- Always use braces for
ifstatements - Ternary for conditional rendering — Use
condition ? <A /> : null, nevercondition && <A />
Styling
- Tailwind CSS v4 with
cn()utility for class merging text-foreground/80for user-facing text sectionsflex-noneon icons to prevent flex shrinksize-*classes for icon dimensions- Component-specific CSS in
ComponentName.cssfiles (notglobals.css)
Components
components/ui/is READ-ONLY (shadcn/ui primitives)- Global customs go in
components/ - Split at 600 lines — Create
Name/Name.tsxdirectory structure - Use
Modalsuffix (e.g.,UserModalnotUserDialog) - Icons: First choice
AppIcon(Iconify), second choice Lucide
State Management
- Zustand for client-side state (stores in
stores/) - React Hook Form + Zod for form validation
- Server actions for mutations (Next.js App Router)
i18n
- User pages: Use
useTrans/getTranswith inline dictionaries for all 12 locales - Admin pages: English only, no translation
- Date/time: Use Luxon exclusively (never
date-fnsfor new code)
Error Handling
- Always
console.errorbefore showing a toast - Generic errors must append: "Please refresh the page and try again."
- User-facing toasts: Use
@/lib/toasthelpers (showSuccessMessage, etc.) - Admin toasts: Use
sonnerdirectly
AI Integration
- Use
@ai-sdk/google-vertexfor AI calls - Always use
buildThinkingProviderOptions(modelId, desiredLevel)fromlib/ai-models.tsto buildproviderOptions— never inlinethinkingConfigmanually - This helper normalizes Prisma's UPPERCASE
ThinkingLevelenum and auto-bumps'minimal'→'low'for models that don't support it (e.g.gemini-3.1-pro-preview) gemini-3.1-pro-previewdoes not supportthinkingLevel: 'minimal'; it requires'low'or higher- Cheap classification routes (intake plan/resolve, preflight, spreads/suggest) must use
gemini-3-flash-preview— Flash supports all thinking levels including'minimal'
Database Workflow
Schema Changes
- Edit
prisma/schema.prisma - Run
npx prisma db pushto apply - Run
npx prisma generateto update client
Reset Database
bash
npx prisma migrate reset && npx prisma generate && npx prisma db seedSeed Individual Data
bash
pnpm seed:oneTesting
Playwright
The project uses Playwright for end-to-end testing:
bash
npx playwright testDevbox Testing Dashboard
For manual testing of credits, subscriptions, and user flows, use the devbox testing tools:
- Stripe testing:
/devbox/stripe-testing - User switching:
/devbox/user-testing
Quick presets: Fresh User, Broke User, Gold Subscriber, Diamond Whale, Rate Limited.
Key Files Reference
| File | Purpose |
|---|---|
proxy.ts | Middleware (route protection, redirects, visitor tracking) |
lib/auth.tsx | Better Auth configuration |
lib/prisma.ts | Prisma client singleton |
lib/redis.ts | Redis connection |
lib/queue.ts | BullMQ queue definitions |
lib/credits.ts | Credit deduction logic |
env.ts | Environment variable validation (t3-env) |
ecosystem.config.cjs | PM2 production config |
config/consts.ts | Application constants |
Important Notes
- Middleware file: Named
proxy.ts, NOTmiddleware.ts - Protected routes: Must check against
routing.localesto handle/en/me,/zh_CN/me, etc. - Visitor tracking: The
VISITOR_COOKIEis HTTP-only; use<PageViewTracker />component (no client-side JS cookie reading) - After schema changes: Always run
npx prisma generatewhen the task is complete