Deployment Checklist
The shortest path from "works locally" to a real production URL.
1. Make it work locally first
Do not skip this.
npx teenybase deploy --local --yes
npx teenybase devBefore you deploy, verify at least these:
curl http://localhost:8787/api/v1/healthThen check these in the browser:
http://localhost:8787/api/v1/doc/ui- your main sign-up flow
- your main login flow
- at least one protected write action
2. Log in to Cloudflare
Teenybase deploys to your own Cloudflare account (the Workers free plan is enough to start). Authenticate once:
npx wrangler loginIn CI or other non-browser setups, set CLOUDFLARE_API_TOKEN (Workers Scripts and D1 edit permissions) and CLOUDFLARE_ACCOUNT_ID instead.
3. Production secrets
The first remote deploy generates any missing secrets into .prod.vars with random values and uploads them with the worker:
JWT_SECRETJWT_SECRET_USERSADMIN_JWT_SECRETADMIN_SERVICE_TOKENPOCKET_UI_VIEWER_PASSWORDPOCKET_UI_EDITOR_PASSWORD
To choose your own values, create .prod.vars before the first deploy (for example cp .dev.vars .prod.vars, then replace every value with the output of openssl rand -base64 32). Never reuse the dev defaults. .prod.vars is gitignored; keep it private.
4. First remote deploy
Make sure RESPOND_WITH_ERRORS is not set to true in .prod.vars or under vars in wrangler.jsonc, so failed SQL generation/execution errors do not return raw SQL errors to the caller.
npx teenybase deploy --remote --yesThe first remote deploy creates the D1 database (replacing TEENY_AUTO_CREATE in wrangler.jsonc; commit that file afterwards), uploads the secrets, deploys the worker and applies the migrations.
5. Copy the exact production URL
deploy --remote prints the worker URL at the end (+ Deployed: https://...) and saves it as apiRoute in infra.jsonc. Copy that exact URL.
Use that exact URL for:
- your frontend API base URL
- Google OAuth callback/origin setup
Set appUrl separately based on where users should land after browser auth and where email links should point to:
- frontend app: set
appUrlto the frontend's public URL - backend-only app (no frontend yet): set
appUrlto your real deployed backend URL
For email verification and password reset, appUrl is also the base for the link templates teenybase embeds in outgoing emails ({appUrl}/reset-password/{token} and {appUrl}/verify-email/{token}). Your frontend hosts those routes. See Email Verification & Password Reset.
6. Update appUrl and deploy again if needed
If appUrl was still set to localhost or a placeholder value, fix it now.
export default {
appUrl: 'https://YOUR_REAL_FRONTEND_URL_HERE',
// rest of config
}Then redeploy:
npx teenybase deploy --remote --yes7. Later secret changes
Changing .prod.vars locally does nothing until you upload the new values.
npx teenybase secrets --remote --upload8. Final pre-launch check
Before you hand the URL to users, verify all of these:
apiRouteininfra.jsoncis the URL you expectappUrlmatches the real deployed URL- sign-up works in production
- login works in production
- one protected write action works in production
- if you use Google auth, the provider settings match the deployed URL exactly
- if you send emails, password reset and verification work end to end
.prod.varscontains real secrets, not dev defaults
9. Useful production commands
Stream logs from the deployed worker:
npx teenybase logsBack up the production database:
npx teenybase backup --remoteSee the CLI Reference for all commands.