1. Legal and GDPR
- Company info — fill
LEGAL_COMPANY_NAME,LEGAL_ADDRESS, andLEGAL_REGISTRATION_NUMBERin.env.local(and later in your production env). They render on legal pages and in invoices. - Legal pages — log in as admin, open
/admin-dashboard/cms, and finalize/terms,/privacy,/legal. Also review the built-in/privacy-choicespage so the public rights/opt-out copy matches your actual processors and advertising setup. - Cookie consent — the banner is wired by category (necessary / analytics / marketing). Verify the categories match what you actually load, and test that Global Privacy Control keeps marketing/targeted-advertising consent disabled.
- Account deletion — works out of the box (30-day grace period). Make sure the cron job
process-account-deletionsis enabled in/admin-dashboard/jobs.
2. Production env vars
Two categories — they live differently:
| Type | Examples | Where to set | To change later |
|---|---|---|---|
| Build-time | NEXT_PUBLIC_*, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY | Set before npm run build — they are baked into the JS bundle | Requires a new build/deploy |
| Runtime | STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, SUPABASE_SECRET_KEY, OPENAI_API_KEY | Set on the server / container env | Restart the container; no rebuild needed |
3. Deploy
Pick a deployment target:
4. Production webhooks
The Stripe CLI was only for dev. In production:
- Switch Stripe to live mode and copy the live keys into your production env.
- Open Developers → Webhooks → Add endpoint.
- URL:
https://your-domain.com/api/stripe/webhook - Subscribe to all
customer.subscription.*,invoice.*,charge.*,checkout.session.*,customer.*, andpayment_method.*events. At minimum:checkout.session.completed,customer.subscription.{created,updated,deleted,paused,resumed,trial_will_end},invoice.{paid,payment_failed,payment_action_required},charge.{refunded,dispute.created,dispute.closed},customer.{created,updated,deleted},payment_method.{attached,detached},checkout.session.{async_payment_succeeded,async_payment_failed,expired}. Full list in.claude/rules/billing.md. - Copy the
whsec_...signing secret intoSTRIPE_WEBHOOK_SECRETin prod env. Restart.
5. Observability
- Error logs — set
LOGS_ENABLED=true, generate a strongLOGS_SALT, pick aLOGS_RETENTION_DAYS. Logs surface in/admin-dashboard/logs. - Rate limiting — create an Upstash Redis database and paste
UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN. Without these, rate limits use an in-memory fallback that resets on every deploy. - Jobs API URL — update
app_settings.jobs_api_urlin the database to the production URL so cron triggers reach the right host. - Indexing — set
NEXT_PUBLIC_INDEXABLE=trueonly after legal pages are real and placeholder text is gone.
6. Final smoke tests
Walk through these on the live URL before announcing the launch:
- Landing page renders, no console errors, branding correct
GET /api/healthreturns 200- Magic link arrives within 30 seconds in a real inbox
- Admin can reach
/admin-dashboard - Public user can complete a live checkout
- A chat message streams from the LLM and credits decrement
- Cookie banner appears for new visitors and respects choices
- Footer links expose
/privacy,/privacy-choices,/terms,/legal, and Cookie settings - Legal pages have your real company info, not placeholders
You are live when…
- All 8 smoke tests above pass on the production URL
- Stripe webhooks deliver successfully (check the Stripe dashboard log)
- Scheduled jobs ran at least once (check
job_runs) - You sent a magic link to a teammate and they got in
Where to next?
The onboarding is done. From here, dive into specific features as you need them:
- Multi-Tenancy (B2C vs B2B) — workspaces, roles, invitations
- AI Integration — agents, RAG, prompt caching
- Background Jobs — cron, webhooks, retries
- Security — OWASP checklist, CSP, headers
- Full category index — everything else