Fix guides / Environment variables undefined after deploy
Environment variables work locally but are undefined after deploy
Your API key or Supabase URL works in development. After deploying, the app shows a blank screen or errors like supabaseUrl is required, and logging the variable prints undefined.
Cause 1: the .env file is not deployed (by design)
Your .env or .env.local file is in .gitignore, which is correct because it holds secrets. That also means Vercel never sees it. Add each variable in Vercel under Project Settings, then Environment Variables, for the Production (and Preview) environment.
Cause 2: the browser can only see prefixed variables
| Framework | Prefix needed for browser code | Read it with |
|---|---|---|
| Vite (Lovable, Bolt, most React apps) | VITE_ | import.meta.env.VITE_SUPABASE_URL |
| Next.js | NEXT_PUBLIC_ | process.env.NEXT_PUBLIC_SUPABASE_URL |
| Create React App | REACT_APP_ | process.env.REACT_APP_API_URL |
A variable without the prefix is only available on the server. If your component reads process.env.SUPABASE_URL in the browser, it will be undefined.
Cause 3: you added the variable but did not redeploy
For Vite and for NEXT_PUBLIC_ values in Next.js, the value is baked into the JavaScript at build time. Changing it in Vercel does nothing until you redeploy: Deployments, then the three dots on the latest one, then Redeploy.
Cause 4: typos and quotes
Names are case sensitive. Paste the value without surrounding quotes or a trailing space or newline.
Important: never prefix a secret
Anything with VITE_ or NEXT_PUBLIC_ is visible to anyone who opens your site. The Supabase anon key is designed to be public (RLS protects your data). Your Supabase service_role key, OpenAI key, or Stripe secret key are not. Those must stay server-side, in an API route or edge function, without a public prefix.
Quick test
// temporary, remove after checking
console.log('url set?', Boolean(import.meta.env.VITE_SUPABASE_URL));
Request a fix
Last updated 2026-10-19.