Skip to content

Production Deployment Checklist

app.neemias.app and api.neemias.app are production environments. Local pnpm dev is development-only. This checklist covers the full production setup — Cloudflare Dashboard + code.


1. Environment Variables — Cloudflare Dashboard

These must be set manually in the Cloudflare Dashboard. They are never committed.

Cloudflare Workers (api.neemias.app)

Navigate to Workers & Pages → neemias → Settings → Variables.

VariableTypeRequiredDescription
AUTH_MODEPlain textYesSet to jwt. Default is dev (accepts any token — insecure).
AUTH_JWT_SECRETSecretYesGenerate with openssl rand -hex 32. Used to sign/verify JWT.
ENVIRONMENTPlain textYesSet to production. Blocks dev-only endpoints like /api/v1/_seed.

Optional (dev-mode tokens): For local development against the remote API:

  • AUTH_DEV_ADMIN_TOKEN — e.g. dev-admin-token
  • AUTH_DEV_CALLER_TOKEN, AUTH_DEV_COORDENACAO_TOKEN, etc.

Cloudflare Pages (app.neemias.app)

Navigate to Workers & Pages → neemias-app → Settings → Environment Variables.

VariableTypeRequiredDescription
DEPLOY_ENVPlain textYesSet to prod. Without this, the app's seed runs automatically.
VITE_BACKEND_URLPlain textYesSet to https://api.neemias.app

2. Deploy Pipeline

bash
# 1. Frontend — build + Pages auto-deploy
pnpm build:app
git add -A && git commit -m "..."
git push
# → Cloudflare Pages builds and deploys automatically

# 2. Worker — direct deploy
pnpm deploy:worker

# 3. Apply D1 migrations (if any)
pnpm db:migrate:remote

What build:app does (v0.54.0+)

  1. Exports NODE_ENV=production so generate-headers.ts uses production CSP
  2. Runs scripts/generate-headers.ts via app/csp.config.ts — writes CSP into app/public/_headers
  3. Runs Vite production build (Rolldown bundler)
  4. Output goes to app/dist/. Pages serves from this directory

CSP note: Production CSP uses edge-generated dynamic nonces via Pages Middleware (functions/_middleware.ts). See security docs for details.


3. Security Checklist

  • [ ] AUTH_MODE=jwt (not dev)
  • [ ] AUTH_JWT_SECRET is a strong random value stored as a Secret
  • [ ] ENVIRONMENT=production (blocks seed endpoint)
  • [ ] DEPLOY_ENV=prod (on Pages — blocks frontend seed)
  • [ ] CSP mode is correct for production (dynamic nonces)
  • [ ] NODE_ENV=production exported during pnpm build:app
  • [ ] scripts/pre-deploy-check.sh exits 0
  • [ ] scripts/validate-csp.sh passes
  • [ ] frame-ancestors 'none' in CSP
  • [ ] Strict-Transport-Security: max-age=63072000 active
  • [ ] No dev-mode tokens exposed in production
  • [ ] All D1 migrations applied (pnpm db:migrate:remote)
  • [ ] Rollback tag identified (previous v* tag for quick revert)
  • [ ] Visual smoke test: login page loads, no CSP console errors

Distributed under MIT License.