Deployment Guide
Infrastructure Requirements
| Component | Requirement | Purpose |
|---|---|---|
| Server | Linux VM or container, Node.js 20+ | Application hosting |
| PostgreSQL | Version 18 | Primary database |
| Redis | Version 7+ | Queue, pub/sub, caching |
| Cloudflare R2 | S3-compatible bucket | File storage (images, uploads) |
| Google Cloud | Vertex AI API enabled | AI model access |
| Stripe | Account with webhooks | Payment processing |
| Resend | API key | Transactional emails |
Deploy Steps
1. Install Dependencies
bash
pnpm install --frozen-lockfile2. Generate Prisma Client
bash
npx prisma generate3. Apply Database Schema
bash
npx prisma db pushFor first-time setup, also run the seed:
bash
npx prisma db seed4. Build
bash
pnpm build5. Start with PM2
bash
pm2 start ecosystem.config.cjs --env productionThis starts all six processes:
| Process | Description |
|---|---|
mysticx-web | Next.js web server (cluster mode, all CPUs) |
mysticx-worker | Tarot reading worker |
mysticx-insights-worker | Guidance/journey generation worker |
mysticx-telegram-bot | Telegram bot |
mysticx-question-insights-worker | Admin question insights analysis worker |
mysticx-translation-worker | Blog 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 startupLogs
All processes write logs to the logs/ directory:
| File | Process |
|---|---|
logs/pm2-out.log | Web server stdout |
logs/pm2-error.log | Web server stderr |
logs/worker-out.log | Tarot worker stdout |
logs/worker-error.log | Tarot worker stderr |
logs/insights-worker-out.log | Insights worker stdout |
logs/insights-worker-error.log | Insights worker stderr |
logs/telegram-bot-out.log | Telegram bot stdout |
logs/telegram-bot-error.log | Telegram bot stderr |
logs/question-insights-worker-out.log | Question insights worker stdout |
logs/question-insights-worker-error.log | Question insights worker stderr |
logs/translation-worker-out.log | Translation worker stdout |
logs/translation-worker-error.log | Translation worker stderr |
Stripe Webhook Configuration
Point webhook to: https://your-domain.com/api/auth/stripe/webhook
Subscribe to events:
checkout.session.completedinvoice.payment_succeededcustomer.subscription.updatedcustomer.subscription.deleted
Set the webhook signing secret as STRIPE_WEBHOOK_SECRET.
Cloudflare R2 Setup
Create a bucket and configure:
R2_ACCOUNT_ID— Cloudflare account IDR2_ACCESS_KEY_ID— R2 API token access keyR2_SECRET_ACCESS_KEY— R2 API token secret
Used for: card skin images, reader avatars, user avatar uploads, feedback screenshots.
Google Vertex AI Setup
- Create a GCP project with Vertex AI API enabled
- Create a service account with the
Vertex AI Userrole - Download the JSON key file
- Set
GOOGLE_APPLICATION_CREDENTIALSto the key file path - Set
GOOGLE_VERTEX_PROJECTandGOOGLE_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:
- Web server: Visit the site, check pages load
- Auth: Test sign-in and sign-up flows
- Readings: Submit a test reading and verify streaming works
- Worker: Check PM2 logs for worker startup messages
- Stripe: Test a checkout flow in test mode
- Telegram: Send
/startto 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