Skip to content

Development Guide

Prerequisites

ToolVersionPurpose
Node.js20+Runtime
pnpm9+Package manager
PostgreSQL18Database
Redis7+Queue and cache

Local Setup

1. Install Dependencies

bash
pnpm install

2. Configure Environment

bash
cp env.example .env

Fill in the required variables. At minimum for local development:

  • DATABASE_URL — PostgreSQL connection string
  • BETTER_AUTH_SECRET — Generate with openssl rand -base64 32
  • BETTER_AUTH_URLhttp://localhost:3000
  • GOOGLE_APPLICATION_CREDENTIALS — Path to Vertex AI service account key
  • GOOGLE_VERTEX_PROJECT — GCP project ID
  • GOOGLE_VERTEX_LOCATIONglobal

3. Database

bash
# Apply schema
npx prisma db push

# Generate client
npx prisma generate

# Seed data
npx prisma db seed

To 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-bot

Or 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 worker

Coding Conventions

TypeScript

  • No any — Strict typing throughout
  • Types over interfaces — Use type TName (no interface)
  • Inline props — Component props are defined inline, not extracted
  • Always use braces for if statements
  • Ternary for conditional rendering — Use condition ? <A /> : null, never condition && <A />

Styling

  • Tailwind CSS v4 with cn() utility for class merging
  • text-foreground/80 for user-facing text sections
  • flex-none on icons to prevent flex shrink
  • size-* classes for icon dimensions
  • Component-specific CSS in ComponentName.css files (not globals.css)

Components

  • components/ui/ is READ-ONLY (shadcn/ui primitives)
  • Global customs go in components/
  • Split at 600 lines — Create Name/Name.tsx directory structure
  • Use Modal suffix (e.g., UserModal not UserDialog)
  • 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/getTrans with inline dictionaries for all 12 locales
  • Admin pages: English only, no translation
  • Date/time: Use Luxon exclusively (never date-fns for new code)

Error Handling

  • Always console.error before showing a toast
  • Generic errors must append: "Please refresh the page and try again."
  • User-facing toasts: Use @/lib/toast helpers (showSuccessMessage, etc.)
  • Admin toasts: Use sonner directly

AI Integration

  • Use @ai-sdk/google-vertex for AI calls
  • Always use buildThinkingProviderOptions(modelId, desiredLevel) from lib/ai-models.ts to build providerOptions — never inline thinkingConfig manually
  • This helper normalizes Prisma's UPPERCASE ThinkingLevel enum and auto-bumps 'minimal''low' for models that don't support it (e.g. gemini-3.1-pro-preview)
  • gemini-3.1-pro-preview does not support thinkingLevel: '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

  1. Edit prisma/schema.prisma
  2. Run npx prisma db push to apply
  3. Run npx prisma generate to update client

Reset Database

bash
npx prisma migrate reset && npx prisma generate && npx prisma db seed

Seed Individual Data

bash
pnpm seed:one

Testing

Playwright

The project uses Playwright for end-to-end testing:

bash
npx playwright test

Devbox 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

FilePurpose
proxy.tsMiddleware (route protection, redirects, visitor tracking)
lib/auth.tsxBetter Auth configuration
lib/prisma.tsPrisma client singleton
lib/redis.tsRedis connection
lib/queue.tsBullMQ queue definitions
lib/credits.tsCredit deduction logic
env.tsEnvironment variable validation (t3-env)
ecosystem.config.cjsPM2 production config
config/consts.tsApplication constants

Important Notes

  • Middleware file: Named proxy.ts, NOT middleware.ts
  • Protected routes: Must check against routing.locales to handle /en/me, /zh_CN/me, etc.
  • Visitor tracking: The VISITOR_COOKIE is HTTP-only; use <PageViewTracker /> component (no client-side JS cookie reading)
  • After schema changes: Always run npx prisma generate when the task is complete

Internal documentation for MysticX team