Engineeringenvstripeneonsecurity

The SaaS .env checklist: Next.js, Stripe, Neon, and storage

Required versus optional environment variables for common SaaS kit stacks - and the habits that keep secrets out of git and out of screenshots.

Twenty · July 19, 2026 · 3 min read

The SaaS .env checklist: Next.js, Stripe, Neon, and storage

Treat .env.example as a contract

A good `.env.example` is not a dump of every key the author ever typed. It is a contract with the next human: what must exist for the app to boot, and what merely unlocks email, social login, or analytics.

When that contract is fuzzy, buyers invent variable names, paste production secrets into the wrong file, and open support tickets that look like product bugs.

Think of required variables as the minimum viable production config. Optional variables are features you can stage. Mixing the two in one undifferentiated list is how teams ship without email for three weeks and call it "MVP."

Almost always required on full-stack kits

`DATABASE_URL` points at Neon or another Postgres with SSL. `NEXT_PUBLIC_APP_URL` is the public origin used for redirects, emails, and Open Graph. If the kit ships custom auth, `JWT_SECRET` (or equivalent) signs access tokens and should be long and unique per environment. Billing kits need `STRIPE_SECRET_KEY` and `STRIPE_WEBHOOK_SECRET`. Upload kits need object-storage credentials and often an endpoint URL for R2.

Name mismatches are common across kits. Always prefer the seller's `.env.example` over a blog post - including this one. The env checklist generator is a starting template, not an override.

Public variables that start with `NEXT_PUBLIC_` are visible in the browser bundle. Never put a secret behind that prefix and hope nobody looks.

Often optional on first boot

SMTP credentials for verify and reset mail. Google or GitHub OAuth client ids. A Stripe publishable key when Stripe.js runs in the browser. Analytics ids. Feature flags. You can usually reach `npm run dev` without them, then add them before inviting real users.

Optional does not mean unimportant. Shipping without transactional email means password reset is a support channel. Shipping without webhook secrets means Checkout is theater.

A practical sequence: boot locally with required vars, prove signup and a test purchase, then enable email and OAuth before soft launch.

Habits that prevent incidents

Commit `.env.example` with placeholders only. Never commit `.env` or `.env.local`. Use different secrets for local, preview, and production. Rotate webhook secrets if they appear in a screenshot or a public issue. Keep object-storage buckets private unless the asset is intentionally public.

If you are packaging a kit for Twenty, run the repo health scanner on `git ls-files` before upload. A committed `.env` fails the vibe check immediately and fails review shortly after.

Store production secrets in Vercel (or your host) and treat laptop `.env` files as disposable. When someone leaves the team, rotate.

Generate a printable list, then reconcile

Pick a stack preset in the .env checklist generator, copy the template, and reconcile line by line with the kit you purchased. When the file is complete, walk the deploy checklist so the values you typed actually reach Vercel, Neon, Stripe, and storage in the right order.

Related posts