Ship/Now

Ship it · 2 min

Environment variables

Every variable, what breaks without it, and the two mistakes that produce a 500 with no useful message.

VariableNeededWithout it
NEXT_PUBLIC_SITE_URLAlwaysMetadata, sitemap and Stripe redirects break
NEXT_PUBLIC_SUPABASE_URLAlwaysNo auth, no data
NEXT_PUBLIC_SUPABASE_KEYAlwaysSame
SUPABASE_SECRET_KEYAlwaysThe webhook cannot write
RESEND_API_KEYFor emailSends are skipped, logged, not thrown
EMAIL_FROMFor emailResend rejects the send
STRIPE_SECRET_KEYFor money/api/checkout returns 503, app fine
STRIPE_WEBHOOK_SECRETFor moneyThe webhook returns 503
ADMIN_EMAILSFor /adminNobody can open it
SUPABASE_ACCESS_TOKENFor db:push onlyNever needed at runtime

NEXT_PUBLIC means public

Anything prefixed NEXT_PUBLIC_ is inlined into the JavaScript bundle at build time. It is in your customer's browser, readable in devtools. That is correct for the Supabase publishable key, which is designed for it and is useless without a session because Row Level Security does the work.

It is catastrophic for SUPABASE_SECRET_KEY, which bypasses RLS entirely. Never prefix a secret.

Empty is worse than missing

This is the one that produces a 500 on every route with nothing in the log:

const base = process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000";
new URL("/pricing", base);

?? only falls back on null and undefined. A variable set to an empty string passes straight through, and new URL("/pricing", "") throws. If it is in the root layout, every page dies.

Delete the variable rather than blanking it, or guard on truthiness:

const base = process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000";

Plain, not sensitive

On Vercel, a variable marked Sensitive is write-only: you cannot read it back, and it is not inlined into the bundle. For a NEXT_PUBLIC_ variable that means the browser receives undefined, and the app breaks in production in a way it never did locally.

Use Encrypted, which is the default. Sensitive is for values you will never need to verify, and you will always need to verify them.

Rotating

Anything that has been pasted into a chat, a ticket or a screenshot is burned. Rotate it. It takes a minute in every dashboard here, and it is the cheapest security work you will ever do.

Something wrong or missing on this page? Tell us.