EMZETT.
Login

Environment Variables

In short: Configuration values (API keys, database URLs, secrets) that are set outside the code — e.g. in the Vercel dashboard instead of hard-coded in the repo.

In more detail: Some values (e.g. database connection strings) can be viewed again at any time in the respective dashboard; others (e.g. API keys) are only shown once on creation and have to be regenerated if lost. Vercel additionally has a “Sensitive” flag: once set, the value can no longer be retrieved by anyone — not even via the CLI (vercel env pull) or by the team owner.

Our context: When moving from Bellator to Emzett, almost all env variables (Stripe, Resend, database, Redis) had to be created anew, because they were tied to the old partner accounts.

In Depth

Local configuration

Locally, environment variables in Next.js are usually set via a .env.local file (by convention never committed, excluded in .gitignore — otherwise secrets end up in the Git history, where they remain findable even after the file is deleted later, since Git history forgets nothing by default). Next.js automatically reads several .env* files in a fixed order of priority (.env.local overrides .env.development/.env.production, which in turn override .env) — handy for cleanly separating local development values from real production values without mixing both in the same file.

The NEXT_PUBLIC_ prefix

An important Next.js-specific difference: variables with the NEXT_PUBLIC_ prefix are embedded into the client bundle at build time and are therefore visible to anyone in the browser (e.g. via the developer tools) — all other variables remain available exclusively on the server. Accidentally giving a secret the NEXT_PUBLIC_ prefix effectively makes it public. Technically this happens because Next.js replaces all process.env.NEXT_PUBLIC_* references in the code directly with the actual value at build time (string substitution at build time) — it is NOT a runtime lookup, which is why changing these values always requires a new build to take effect.

# .env.local (never commit)
DATABASE_URL=postgresql://...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...  # deliberately public, for client-side Stripe.js
STRIPE_SECRET_KEY=sk_live_...                    # stays on the server

Environment separation at Vercel

At Vercel, values are additionally managed separately per environment (production/preview/development) — a preview deploy can, for example, work with a test database instead of the real production database, without anything having to be distinguished in the code. This is especially valuable in destructive test scenarios: a preview deploy that accidentally deletes or changes test data therefore never hits the real production database, as long as the environment separation is strictly maintained.

The “Sensitive” flag

Vercel additionally has a “Sensitive” flag: once set, the value can no longer be retrieved by anyone — not even via the CLI (vercel env pull) or by the team owner. This is a deliberate one-way street: the value can still be used by the application at runtime, but nobody can read it back in plain text afterwards, even with full administrative rights for the project. In practice this means: before setting a sensitive value as “Sensitive”, it should be stored safely elsewhere (e.g. in a password manager) — a lost sensitive value can only be recovered by completely regenerating it at the original provider, not by reading it out of Vercel again.

See also: Vercel, Bearer token