Going to production
Set secrets, migrate the database, deploy the Worker and finish setup in the CMS and Stripe.
Once your resources are set up (see Cloudflare setup), going live takes a few commands.
Set the secrets
Run bunx wrangler secret put for BETTER_AUTH_SECRET, STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET.
Migrate the database
Run bun run db:migrate to apply the app migrations to the remote D1 database.
Deploy
Run bun run deploy. It builds with your PUBLIC_URL and uploads the Worker.
Set up the CMS
Open /_emdash/admin on your domain, create the admin account, then set the Site URL, title and logo in settings.
Add the Stripe webhook
Point a Stripe webhook at https://yourdomain.com/api/stripe/webhook for the customer.subscription.updated and customer.subscription.deleted events.
bunx wrangler secret put BETTER_AUTH_SECRET
bunx wrangler secret put STRIPE_SECRET_KEY
bunx wrangler secret put STRIPE_WEBHOOK_SECRET
bun run db:migrate
bun run deployLater deploys
- Apply any new migrations with
bun run db:migratebefore the code that needs them. - Run
bun run deploy. bunx wrangler deploy --dry-runshows the bindings and variables without deploying.
Logs
Observability is on in wrangler.jsonc. Stream live logs with bunx wrangler tail, or browse them in the Cloudflare dashboard.
Backups
D1 keeps point-in-time history with Time Travel (30 days on the paid plan, 7 on the free plan). Before a risky change, note the current bookmark so you can restore to it:
bunx wrangler d1 time-travel info my-app-cmswrangler d1 export doesn't work on the CMS database because of its full-text search tables, so use Time Travel there. Media is in the R2 bucket.