supabaseUrl is required

Error: supabaseUrl is required. / import.meta.env.MY_KEY is undefined / process.env.MY_KEY is undefined in the browser

Run the free checkerSee if your live app has this problem, in about 20 seconds.

What you see

It works locally with your .env file. In production the page is blank or the console shows something like:

Error: supabaseUrl is required.

or your code reads undefined where a key or API URL should be.

Why it happens

There are three usual causes.

1. The .env file never reached the host. It is (correctly) in .gitignore, so Vercel, Netlify or Cloudflare never see it. You have to enter the same variables in the host’s dashboard.

2. The variable has no public prefix. Browser code only gets variables that are explicitly marked public:

  • Vite (Bolt, Lovable and most Cursor-built React apps): only variables prefixed with VITE_ are exposed, read through import.meta.env.VITE_…. Others come back undefined.
  • Next.js (v0 and many Cursor apps): only NEXT_PUBLIC_… variables are inlined into browser JavaScript. Variables without the prefix exist only on the server.

3. You changed the value but didn’t rebuild. Both Vite and Next.js replace these variables with their literal values at build time. Next.js’s docs warn that after the build, the app “will no longer respond to changes to these environment variables.” Editing a value in the dashboard does nothing until you redeploy.

Fix it

  1. List every variable your browser code reads: search the code for import.meta.env or process.env.NEXT_PUBLIC_.
  2. Add each one, with its exact name, in your host’s environment settings for the Production environment (and Preview if you use it).
  3. Check the prefix matches your framework (VITE_ or NEXT_PUBLIC_).
  4. Trigger a new deployment so the build picks up the values.

Next.js also supports dynamic lookups like process.env[name], but they are not inlined in the browser. Reference each variable by its full literal name.

The security part (read this)

Anything with a VITE_ or NEXT_PUBLIC_ prefix is pasted into your public JavaScript bundle, where anyone can read it. Vite’s docs say plainly that VITE_* variables “should not contain sensitive information such as API keys.”

  • OK to expose: your Supabase project URL and publishable/anon key (when RLS is on), analytics IDs, public Stripe publishable keys.
  • Never expose: Supabase service_role/secret keys, Stripe secret keys, OpenAI/Anthropic keys, database passwords. Use these only in server code (API routes, serverless or edge functions).

If a secret was ever bundled or committed, rotate it at the provider. Run a secret scanner over the repo history before you make it public.

Check it worked

After redeploying, open DevTools → Network and confirm requests go to the right API URL. Then search the built JS (Sources tab) for the first few characters of your secret keys: they must not be there.