@next-starters/skill-prod-deploy
v1.0.0
Published
The prod half of an ENV-selected runtime-env stack (api→Render, web→Vercel, DB→Supabase Cloud) — the counterpart to runtime-env-config (app-side loader/EnvProvider) and local-dev-stack (local stack).…
Downloads
18
Readme
prod-deploy
The prod half of an ENV-selected runtime-env stack: bringing the same image
up in production the first time on api→Render · web→Vercel · DB→Supabase
Cloud. Counterpart to skills/runtime-env-config (the app-side loader +
EnvProvider chain) and skills/local-dev-stack (the operational local
stack). The load-bearing fact: a git push does not bring prod up — secrets,
DB migrations, and Supabase-cloud auth config are manual, per-env, one-time setup.
Why the loader can't save you
On both platforms the runtime loader finds no .env files:
- Render — the image
.dockerignores.env.*, so they never ship. - Vercel — the runtime
server-preload.cjsnever executes.
So process.env is the only source and every var (secret and the
"non-secret" .env.<stage> set) must be entered in the platform env.
Platform-injected process.env wins (override:false).
The prod side
- Set every var on the platform — not just secrets; the
type:'public'.env.<stage>keys (ENV, URLs, selectors) too. - Inject
ENV=<stage>on each platform — the stage selector, distinct fromNODE_ENV; missing it, the loader falls back to base.env. - Secrets by registry — derive the per-platform list from the env registry's
type/source;.env.<stage>.localis the name list, values entered by hand. - Migrate manually —
db:deploy=db:migrate && db:post(schema → RLS + auth-hook), run against the cloud direct/session URL. No migrate-on-deploy; Drizzle owns the schema. - Supabase Cloud dashboard — register the access-token hook (or JWTs carry no
org/role), set the captcha secret, turn email confirmations ON;
config.tomlcan't carry these. - Connection strings — app
:6543{prepare:false}, migrations:5432{max:1}; but Render egress needs session:5432+sslmode=requirefor both, orECONNREFUSEDon first boot. - Build ≠ runtime —
next buildmust NOT run the preload; runtime env comes from platform injection. - Automate the setup, not the deploy — the first deploy is a deliberate human trigger.
Use it
Read SKILL.md for the 14 invariants (one verifiable todo each) and the red
flags. The last 6 (9–14) were added after a 13-repo rollout of this pattern:
detecting which org/role model applies before picking a verify method,
the DB driver+SSL decision table (the #1 repeated deploy-killing mistake),
checking migration drift + a baseline recipe before running db:deploy on a
pre-existing DB, a near-free rowsecurity=false sweep that's caught a real
live P0, a set of Vercel-specific landmines (ciphertext, ignoreCommand
batched-push bugs, monorepo rootDir-skip), and the JIT-provisioning
onboarding-gap check. Copy the genericized templates from references/:
PROD-DEPLOY-checklist.md— a fill-in checklist to drop into your repo asdocs/PROD-DEPLOY.md.render.yaml— the annotated Render blueprint (ENV, non-secret inline values,sync:falsesecret prompts, the:5432/sslmodecaveat).deploy-env.mjs— a SAFE, dry-run-by-default env pusher for the Render API +vercel env(node deploy-env.mjs --stage <stage>prints the plan;--applyto write; never echoes secret values).
Swap the <scope> / <app> / <stage> placeholders for your own.
Companion
Pairs with skills/runtime-env-config (the loader + EnvProvider chain and the
typed env registry this skill derives the per-platform var lists from) and
skills/local-dev-stack (whose db:post post-schema step is the same db:deploy
run here against the cloud). Canonical schema in docs/ENVIRONMENT-CONFIG.md.
