Two kinds of environment variable
# .env.local — your machine, never committed
DATABASE_URL=postgres://localhost:5432/doors
STRIPE_SECRET_KEY=sk_live_…
NEXT_PUBLIC_SITE_URL=https://domvybe.com
// server component, action, route handler, middleware
process.env.DATABASE_URL // fine
// client component
process.env.DATABASE_URL // undefined
process.env.NEXT_PUBLIC_SITE_URL // works — and is in the JavaScript bundle
The value is inlined into the bundle at build time. Anyone can read it in devtools. A key with that prefix is not a secret, whatever the provider called it — and changing it needs a rebuild, not a restart.
Which file, and when
Commit a .env.example with every key and a dummy value. It is the only documentation of what the project needs that stays correct.
| File | Loaded |
|---|---|
.env | Always — for defaults that are not secret |
.env.local | Always except in tests — gitignored, for your machine |
.env.development / .env.production | Per NODE_ENV |
| The platform’s own variables | In production, and they win |
The build
npm run buildmust pass before you push. Type errors and lint errors fail it by default.- The build reads environment variables — a missing one at build time is not the same failure as a missing one at runtime.
- Static export is right for a purely static site and wrong for everything in this course.
npm run build && npm start # a Node server — the default
# output: "standalone" → .next/standalone, a minimal server for a container
# output: "export" → a folder of static files, and NO server:
# no server actions, no route handlers, no ISR
Where it runs
It is a Node application. Anywhere that runs Node and lets you set environment variables will run it; the differences are in how much of the caching works without configuration.
- Vercel — made by the same people; every feature works on day one.
- A container (Fly, Railway, Render, your own Kubernetes) —
output: "standalone", a Dockerfile,node server.js. - Cloudflare / Netlify — adapters, with occasional gaps around ISR and the Node runtime.
- Static hosting — only with
output: "export".
A checklist before the first deploy
npm run buildpasses locally, with the production environment variables set..env*is gitignored, and every secret is set on the platform instead.- No
NEXT_PUBLIC_variable holds anything private. - The database is reachable from the platform, with a connection limit that matches a serverless environment.
- A real
metadataBase, a favicon, arobots.txtand a sitemap. - Error tracking installed. A 500 nobody hears about is a bug that lives for months.
Watch it after
- The build output, every deploy: a route that turned dynamic, a chunk that doubled.
- Error rate and latency, with an alert, not a dashboard you remember to open.
- Core Web Vitals from real visitors, not only from your laptop.
- The database: connection count, slow queries, and the pool.
And keep the rollback cheap
Every platform can redeploy the previous build in one click. The fastest fix for a bad release is the previous release — then find out what happened, without the pressure of production being broken.