HeHeedza

How do I fix "supabaseUrl is required" in production?

Last reviewed

Short answer

createClient() got undefined because your Supabase URL or key wasn't there when the app was built. Add the variables to your host's Production environment with the exact names and prefix your code reads (VITE_ for Vite, NEXT_PUBLIC_ for Next.js), then trigger a fresh build. Saving the variable alone doesn't change an existing deploy.

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. .env is 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_URL instead of VITE_SUPABASE_URL, or the code reads ..._PUBLISHABLE_KEY while 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.

Fix prompt
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.

Questions

I added the variables. Why is it still broken?

The deployed build was made before you added them. Trigger a new deploy (clear the cache on Netlify) so the values are compiled in.

Is it safe to put the Supabase URL and anon key in the front end?

Yes. They're designed to be public, as long as Row Level Security protects your tables. The service_role or secret key is never safe in the browser.

Why does process.env.NEXT_PUBLIC_X work in one file and not another?

Next.js only inlines public env vars written out literally. Dynamic lookups like process.env[key] stay undefined in the browser.

Sources