Why this happens
Front-end env vars aren't read at runtime. Vite replaces import.meta.env.VITE_* and Next.js inlines process.env.NEXT_PUBLIC_* while building. If the variable is missing at build time, undefined is baked into the JavaScript and createClient(undefined, ...) throws on page load. Usually that crashes the whole app into a blank page.
Common reasons it's missing:
- The variables live in a local
.env(or in Bolt or Lovable's environment), which your host never sees..envis usually git-ignored. - They were added on the host, but only for Preview or Development, not Production.
- They were added after the last build, and nobody redeployed.
- The name or prefix differs:
SUPABASE_URLinstead ofVITE_SUPABASE_URL, or the code reads..._PUBLISHABLE_KEYwhile the host has..._ANON_KEY. - In Next.js, the code reads it dynamically (
process.env[name]), which isn't inlined.
How to fix it, step by step
1. Find the exact names your code reads. Open your Supabase client file (often src/integrations/supabase/client.ts or src/lib/supabase.ts):
// Vite (Lovable, Bolt and most React apps)
const url = import.meta.env.VITE_SUPABASE_URL;
const key = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY; // or VITE_SUPABASE_ANON_KEY
// Next.js: must be written out literally like this
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
const key = process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY;2. Add them on the host, for Production.
- Vercel: Project → Settings → Environment Variables. Add each one with Production ticked, then redeploy. Vercel applies env changes to new deployments only.
- Netlify: Site configuration → Environment variables. Add them, then Deploys → Trigger deploy → Clear cache and deploy site.
- Cloudflare Pages: Settings → Variables and Secrets for the Production environment, then retry the deployment.
Values come from Supabase's Connect dialog or Settings → API Keys. Use the project URL and the publishable (or legacy anon) key only. Never put the secret or service_role key in a VITE_ or NEXT_PUBLIC_ variable.
3. Fail loudly next time. Add a clear check so a missing variable is obvious:
if (!url || !key) {
throw new Error('Missing Supabase env vars at build time: check VITE_SUPABASE_URL / VITE_SUPABASE_PUBLISHABLE_KEY');
}
export const supabase = createClient(url, key);4. Confirm the values are in the build. After deploying, open the live site, then DevTools → Sources (or Network → JS), and search the bundle for supabase.co. If it's there, the URL made it in.
5. Test in a private window and check that the console is clean.
Fix prompt for your AI builder
Paste this into Lovable, Bolt, Cursor, Claude, ChatGPT, Replit, v0 or whichever tool you build with. Replace the bracketed parts first.
Production shows "supabaseUrl is required" (blank page), but it works in the preview. Please:
1. Tell me the exact env var names our Supabase client reads, and the prefix our framework requires.
2. Read them literally (import.meta.env.VITE_... or process.env.NEXT_PUBLIC_...) and throw a clear error if either is missing.
3. Give me step-by-step instructions to add them to my host's Production environment and trigger a fresh build.
Use only the project URL and the publishable/anon key in the browser. Never the service_role or secret key. Don't change any other code.How to catch this next time
This comes back whenever you move hosts, rename a variable, rotate keys or connect a fresh repo. It usually shows up as a completely blank site.
Heedza opens your live landing page and your signup and login pages in a real browser on a schedule. If the page loads blank or the form is missing, it emails you a screenshot and a fix prompt for your AI tool. Its passive scan also flags a Supabase service_role key or other secrets that end up in your public JavaScript, a common side effect of "just make the env vars work" fixes. Try the free scan on your live URL.