Skip to content

Deployment Guide

Infrastructure Requirements

ComponentRequirementPurpose
ServerLinux VM or container, Node.js 20+Application hosting
PostgreSQLVersion 18Primary database
RedisVersion 7+Queue, pub/sub, caching
Cloudflare R2S3-compatible bucketFile storage (images, uploads)
Google CloudVertex AI API enabledAI model access
StripeAccount with webhooksPayment processing
ResendAPI keyTransactional emails

Deploy Steps

1. Install Dependencies

bash
pnpm install --frozen-lockfile

2. Generate Prisma Client

bash
npx prisma generate

3. Apply Database Schema

bash
npx prisma db push

For first-time setup, also run the seed:

bash
npx prisma db seed

4. Build

bash
pnpm build

5. Start with PM2

bash
pm2 start ecosystem.config.cjs --env production

This starts all six processes:

ProcessDescription
mysticx-webNext.js web server (cluster mode, all CPUs)
mysticx-workerTarot reading worker
mysticx-insights-workerGuidance/journey generation worker
mysticx-telegram-botTelegram bot
mysticx-question-insights-workerAdmin question insights analysis worker
mysticx-translation-workerBlog auto-translation worker

Automated Deployment

Two deployment scripts are included:

  • deploy-dev.sh — Deploy to the dev server (port 3032)
  • deploy-prod.sh — Deploy to the prod server (port 3033)

PM2 Management

bash
# View all processes
pm2 list

# Monitor in real time
pm2 monit

# View logs
pm2 logs
pm2 logs mysticx-web
pm2 logs mysticx-worker

# Restart a process
pm2 restart mysticx-web
pm2 restart mysticx-worker

# Reload with zero downtime (cluster mode only)
pm2 reload mysticx-web

# Stop all
pm2 stop all

# Save process list for auto-restart on reboot
pm2 save
pm2 startup

Logs

All processes write logs to the logs/ directory:

FileProcess
logs/pm2-out.logWeb server stdout
logs/pm2-error.logWeb server stderr
logs/worker-out.logTarot worker stdout
logs/worker-error.logTarot worker stderr
logs/insights-worker-out.logInsights worker stdout
logs/insights-worker-error.logInsights worker stderr
logs/telegram-bot-out.logTelegram bot stdout
logs/telegram-bot-error.logTelegram bot stderr
logs/question-insights-worker-out.logQuestion insights worker stdout
logs/question-insights-worker-error.logQuestion insights worker stderr
logs/translation-worker-out.logTranslation worker stdout
logs/translation-worker-error.logTranslation worker stderr

Stripe Webhook Configuration

Point webhook to: https://your-domain.com/api/auth/stripe/webhook

Subscribe to events:

  • checkout.session.completed
  • invoice.payment_succeeded
  • customer.subscription.updated
  • customer.subscription.deleted

Set the webhook signing secret as STRIPE_WEBHOOK_SECRET.

Cloudflare R2 Setup

Create a bucket and configure:

  • R2_ACCOUNT_ID — Cloudflare account ID
  • R2_ACCESS_KEY_ID — R2 API token access key
  • R2_SECRET_ACCESS_KEY — R2 API token secret

Used for: card skin images, reader avatars, user avatar uploads, feedback screenshots.

Google Vertex AI Setup

  1. Create a GCP project with Vertex AI API enabled
  2. Create a service account with the Vertex AI User role
  3. Download the JSON key file
  4. Set GOOGLE_APPLICATION_CREDENTIALS to the key file path
  5. Set GOOGLE_VERTEX_PROJECT and GOOGLE_VERTEX_LOCATION

Environment Checklist

Before deploying, ensure all required environment variables are set:

# Core
DATABASE_URL=
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=
NEXT_PUBLIC_APP_ENV=production

# Auth
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
RESEND_API_KEY=
EMAIL_FROM=

# AI
GOOGLE_APPLICATION_CREDENTIALS=
GOOGLE_VERTEX_PROJECT=
GOOGLE_VERTEX_LOCATION=

# Storage
R2_ACCOUNT_ID=
R2_ACCESS_KEY_ID=
R2_SECRET_ACCESS_KEY=

# Payments
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=

# Redis (if not localhost)
REDIS_HOST=
REDIS_PORT=

# Telegram (optional)
TELEGRAM_BOT_TOKEN=
INTERNAL_API_KEY=

Health Checks

After deployment, verify:

  1. Web server: Visit the site, check pages load
  2. Auth: Test sign-in and sign-up flows
  3. Readings: Submit a test reading and verify streaming works
  4. Worker: Check PM2 logs for worker startup messages
  5. Stripe: Test a checkout flow in test mode
  6. Telegram: Send /start to the bot (if enabled)

Scaling

  • The web server runs in PM2 cluster mode and scales horizontally across CPU cores
  • Workers are single-instance by design (BullMQ handles job locking)
  • For higher throughput, the Tarot Worker can be scaled to multiple instances with BullMQ's built-in concurrency
  • PostgreSQL connection pooling is managed by Prisma's @prisma/adapter-pg

Internal documentation for MysticX team