Deployment and Security Checklist
Deploy the web and admin apps with explicit migrations, cron, readiness, trusted networking, and production security controls.
Synced with starter commit
e632762.
Use this as the final adopter checklist, after the app works locally. The goal is not merely a green deployment: it is a release you can authenticate, bill, operate, restore, and administer without development shortcuts.
Choose the deployment shape
- The web app and admin console are separate builds and should use separate origins. They may share one repository, database, auth secret, and release tag.
- Vercel is documented because
vercel.jsonsupplies cron scheduling, but any Node host works if it provides PostgreSQL, Redis, HTTPS, environment secrets, and an authenticated scheduler. - Use a pooled PostgreSQL URL for serverless traffic and, when the provider requires it, a direct URL for migrations. Run migrations before promoting code; they are intentionally not part of the build.
- Start CSP in report-only mode, observe the hosts used by analytics, Turnstile, Stripe, and storage, then test enforcement before enabling it.
Ready to launch means: both apps build from the same release, migrations are verified, /api/ready is healthy, backups can be restored, the selected queue runner and Stripe webhooks complete a real test, no demo flags exist in production, and read-only/read-write admin access behaves as intended.
Deploy the web app and apps/admin as separate services with separate origins. Use Node >=24.22.1 <25 and pnpm 10.22.0, run pnpm lint, pnpm test:cov, and pnpm build, then apply database migrations explicitly with pnpm db:migrate:prod and pnpm db:check:prod. Migrations are never an automatic build step.
Required Production Controls
- Strong
BETTER_AUTH_SECRET, correct public/auth URLs, production PostgreSQL, and backups with restore drills. - Redis-backed distributed rate limiting and an explicitly trusted client-IP header/source.
- Production Turnstile keys when captcha is enabled; demo features and development auth-link logging disabled.
CRON_SECRETand one default queue runner: authenticated/api/cron/jobsevery five minutes, a boundedpnpm jobs:run --production, orpnpm jobs:work --production. The includedvercel.jsonconfigures the HTTP schedule.- Stripe live keys, verified webhook, safe Billing Portal configuration, and the four primary Price IDs required by the current validator.
- Private S3-compatible storage credentials, least-privilege access, correct CORS, and short signed URLs.
- A verified email sender domain and a data-retention/legal policy reviewed for the markets you serve.
Use /api/health for liveness and /api/ready for deployment readiness. The latter checks environment, database, migration state, Redis, and queue health; a degraded queue is an operational signal even if requests still serve.
Security headers include production HSTS and a report-only CSP path. Observe CSP reports before enforcing a policy compatible with your analytics, captcha, payments, and storage hosts. After deploy, smoke-test auth, organization isolation, checkout/webhooks, queue execution, exports/deletion, and admin MFA. Read DEPLOYMENT.md, docs/security-headers.md, and .env.example in the starter before launch.
The current release also ships hardened images for web, admin, worker, and Content Studio, plus pnpm launch:check to compose configuration, containers, migrations, integrity, retention, tests, and builds. Use Containers and Launch Readiness and prove recovery with Backups, Retention, and Restore Drills.
Validate the real production configuration
Run pnpm env:setup:prod to prepare .env.production.local, then pnpm env:check:prod. Deploy web and Admin with the complete required settings: PostgreSQL, Redis, auth/cron secrets, public/auth origins, Resend and sender, Stripe private/webhook keys, portal configuration and four Prices, and private storage credentials. These provider settings are required by the shared production validator even if a screen does not use them. Empty keys do not disable billing or storage; removing a capability requires changing its validation and runtime deliberately.
Admin needs its own BETTER_AUTH_URL and NEXT_PUBLIC_AUTH_BASE_URL; its NEXT_PUBLIC_WEB_URL remains the customer origin. Supply production variables to the portable worker and release commands through the host's secret manager. Use the environment guide for exact sharing/loading rules. Apply 0037_neat_excalibur.sql before the auth upgrade; apply the independent Payload migration before upgrading Studio.
Containers and Launch Readiness
Build the web, admin, worker, and Content Studio images, keep migrations separate, and run the complete production launch audit.
Five-Credit Image Generation Workflow
Trace the starter's complete asynchronous paid task through authentication, entitlements, idempotent credits, durable work, private storage, and failure compensation.