Next.jsEnv vars

process.env.NEXT_PUBLIC_... is undefined in the browser

process.env.NEXT_PUBLIC_SUPABASE_URL is undefined

In short: Next.js only exposes env vars to browser code when their name starts with NEXT_PUBLIC_, and it inlines them at build time.

Why it happens

Either the variable is missing from .env.local, it lacks the NEXT_PUBLIC_ prefix, the dev server wasn't restarted after you added it, or it's being read dynamically (process.env[name]), which Next.js can't inline.

How to fix it

  1. Check .env.local at the project root (next to package.json) has the exact name, with no quotes issues or spaces around =.
  2. Browser code needs the NEXT_PUBLIC_ prefix. Server-only code (route handlers, server actions) can read unprefixed vars.
  3. Restart next dev. Env files are read at startup.
  4. Reference it literally: process.env.NEXT_PUBLIC_API_URL, not process.env[key].
  5. On your host (Vercel, Netlify, Cloudflare), add the same variable and redeploy, because public vars are baked into the build.
Don't: Never add NEXT_PUBLIC_ to a secret (OpenAI key, Stripe secret key, Supabase secret/service_role key). Anything with that prefix is visible to every visitor.

Copy-paste fix prompt

3 · The fix promptPaste into Cursor, Claude Code, Codex, Lovable, Bolt, Replit or v0
I'm getting this error in my app:

process.env.NEXT_PUBLIC_SUPABASE_URL is undefined

[Paste the full error, stack trace, and the file it points to here]

Likely cause: Next.js only exposes env vars to browser code when their name starts with NEXT_PUBLIC_, and it inlines them at build time.

Task: List every env var this app reads, mark which run in the browser vs. the server, and check each browser one uses the NEXT_PUBLIC_ prefix and is referenced literally. Flag any secret that is wrongly exposed.

Rules:
- First explain the root cause in 2 sentences and list the files you'll change.
- Make the smallest change that fixes it. Don't refactor unrelated code.
- Don't disable security or checks (RLS, auth, signature verification, type checking, CORS allow-all) to make the error disappear.
- Never print or hard-code secret keys.
- Finish by telling me exactly how to verify the fix.

Common with: Cursor, v0, Bolt, Claude Code. Last reviewed 2026-11-13.

Related fixes

← All fixes · Still stuck? Use the diagnose-first prompt