pingbuddy

blog

Error: supabaseUrl is required — How to Fix It After Deploy

Your Supabase app works locally but shows a white screen in production with "supabaseUrl is required". Here's how to fix your environment variables.

6 min readSupabaseVercelFixesBlank screen

Your app works on your computer. It works in the preview. You deploy it, open the live address, and get a white page. The browser console shows one line:

Error: supabaseUrl is required.

This error is one of the most common reasons a freshly deployed Supabase app shows a blank screen. The good news: it's almost never a bug in your code. It's a setting that didn't make it from your computer to your hosting service.

What you see

  • Locally and in the preview, everything works.
  • In production, the page stays white (or partly white).
  • In the browser console there's a red error: supabaseUrl is required.

How to open the console:

  • Chrome or Edge: right-click the page, choose Inspect, then the Console tab. Or press F12 (Cmd + Option + I on a Mac).
  • Safari: first turn on the developer tools in Safari → Settings → Advanced (the option is called "Show features for web developers" in recent versions, "Show Develop menu in menu bar" in older ones). Then choose Develop → Show JavaScript Console, or press Cmd + Option + C.

Reload the page with the console open, so you see the error from the start.

Why it happens

Your app creates a Supabase client when it starts. Supabase's JavaScript docs show it like this:

import { createClient } from "@supabase/supabase-js";

const supabase = createClient("https://xyzcompany.supabase.co", "your-publishable-key");

Real apps don't paste the address directly. They read it from environment variables. In a Vite app (Lovable, Bolt and many Cursor projects use Vite), the code usually looks like this:

import { createClient } from "@supabase/supabase-js";

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseKey = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY;

export const supabase = createClient(supabaseUrl, supabaseKey);

If VITE_SUPABASE_URL is empty when the app is built, supabaseUrl is undefined, and createClient stops with "supabaseUrl is required". Because this happens before anything is drawn, the whole page stays white.

The names in your project may differ — VITE_SUPABASE_ANON_KEY instead of ..._PUBLISHABLE_KEY, for example. Open the file that calls createClient (often src/lib/supabase.ts or src/integrations/supabase/client.ts) and note the exact names it reads. You'll need them below.

The 5 usual causes

1. The .env file never reached the host

Locally, the values come from a .env file. That file is usually listed in .gitignore, so it isn't uploaded to GitHub, and Vercel or Netlify never see it. You have to add the same variables in the host's settings.

2. The prefix is wrong

Build tools only put variables with a specific prefix into browser code:

  • Vite: Vite's docs say only variables starting with VITE_ are exposed to your code, as import.meta.env.VITE_.... A variable named SUPABASE_URL is invisible to the browser.
  • Next.js: in the browser, only variables starting with NEXT_PUBLIC_ are available (process.env.NEXT_PUBLIC_SUPABASE_URL). Next.js replaces them with their values when it builds the app.

The name in the host's settings must match the name in your code exactly, including the prefix.

3. The variable was added, but the app wasn't rebuilt

Vite's docs explain that these variables are replaced with their values at build time. The live app contains whatever the values were during its last build. Adding a variable afterwards changes nothing until you build and deploy again. Next.js works the same way for NEXT_PUBLIC_ variables.

4. The variable is only enabled for Preview

On Vercel, each variable can be enabled for Production, Preview and Development separately. Vercel's docs describe a Production variable as applied to your next Production deployment. If you only ticked Preview, your preview works and production doesn't — exactly the symptom here.

5. A typo or a stray space

VITE_SUPABSE_URL, a space at the end of the name, a value pasted with quotes around it, or a URL copied without https://. Compare character by character with what your code reads and with the URL in your Supabase project's settings.

Fix it on Vercel

  1. Open your project in the Vercel dashboard and go to Settings → Environment Variables.
  2. Add each variable your code reads, for example:
    • Key VITE_SUPABASE_URL, value https://<your-project-ref>.supabase.co
    • Key VITE_SUPABASE_PUBLISHABLE_KEY (or whatever name your code uses), value your project's publishable or anon key
  3. Under environments, make sure Production is ticked (and Preview, if you use preview links).
  4. Save.
  5. Go to Deployments, open the menu (⋯) on the latest production deployment and choose Redeploy. Or push any new commit.
  6. When the new deployment is Ready, test it (see "How to check the fix worked" below).

Copy the values from Supabase rather than typing them: in your Supabase project, the API settings show the project URL and the keys.

Fix it on Netlify

  1. In the Netlify dashboard, open your site and go to Site configuration → Environment variables.
  2. Add the same variables with the same names and values.
  3. Netlify uses these values during the build, so start a new one: go to Deploys and choose Trigger deploy → Deploy site.

If you deploy by dragging a folder into Netlify instead of connecting a repository, there's no build on Netlify's side: the values must already be in the folder you built on your computer. Build again locally with the right .env, then upload the new folder.

Which Supabase key is safe in the browser

Everything with a VITE_ or NEXT_PUBLIC_ prefix ends up in code that every visitor can read. So only put keys there that are meant to be public.

Supabase's API keys documentation describes two kinds:

  • Publishable key (sb_publishable_...) or the older anon key: for browsers and apps. Low privileges; your data is protected by Row Level Security, so make sure RLS is turned on for your tables.
  • Secret key (sb_secret_...) or the older service_role key: full access to your project, bypassing Row Level Security. Only for servers you control. Never give it a VITE_ or NEXT_PUBLIC_ prefix.

If a secret key was ever in your browser code, treat it as leaked: see what to do about an exposed API key.

How to check the fix worked

  1. Open the live site in a private (incognito) window, so nothing old is cached.
  2. Open the console before the page loads, then reload.
  3. The supabaseUrl is required error should be gone and the page should draw.
  4. Try something that talks to Supabase: sign in, or open a page with data.

If the error is gone but data still doesn't load, look at the Network tab for failed requests to supabase.co. That's a different problem — see Supabase "Failed to fetch". Also check that Supabase itself is fine on our Supabase status page.

If the page is white with a different error, our blank white screen guide covers the other usual causes, and why a Bolt.new app stops working after deploy covers host settings in more depth. If the home page works but other pages give a 404 after a refresh, see Vercel 404 NOT_FOUND on page refresh.

Why normal uptime monitors miss this

A white screen caused by this error is invisible to most uptime monitoring. The server sends your index.html and JavaScript perfectly, with status 200 OK. The crash happens afterwards, inside the visitor's browser. A monitor that only looks at the status code reports "up" while every visitor sees a blank page.

Pingbuddy is built for exactly this. Besides checking your site every 5 minutes, it opens your app in a real browser every 30 minutes on Free (every 10 on Pro) and looks at what's actually on screen. If the page is blank or shows an error like supabaseUrl is required, you get an alert on Telegram or by email with a screenshot, the likely cause in plain English and a prompt you can paste into Lovable, Bolt or Cursor to fix it. (On Free, the screenshot and explanation are included for 10 problems a month; the alert itself always goes out.)

Two habits help on top of that:

  • Test the live site in a private window after every deploy, with the console open. It takes a minute.
  • Run a free checkup after a deploy. It shows whether your site answers and how fast, when the SSL certificate and domain expire, and whether any secret keys are visible in its public code.

Quick checklist

  • Find the exact variable names your code passes to createClient.
  • Add them in the host's settings, with the VITE_ or NEXT_PUBLIC_ prefix.
  • Enable them for Production.
  • Redeploy — a new build is required.
  • Only the publishable/anon key goes in the browser, never the secret/service_role key.
  • Test in a private window with the console open.

FAQ

Why does my app work locally but not after deploy?
Locally, your app reads the Supabase address from the .env file on your computer. That file is usually not uploaded (it's in .gitignore), so the hosting service builds your app without it. Add the same variables in your host's settings and build again.
I added the variable on Vercel. Why do I still see the error?
Vite and Next.js put these values into your app when it's built. A variable added after the last build isn't in the live app yet. Redeploy, and check that the variable is enabled for the Production environment, not only Preview.
Is it safe to put my Supabase key in VITE_ or NEXT_PUBLIC_ variables?
Only the publishable key (or the older anon key), which Supabase designed for browsers, with Row Level Security turned on for your tables. Never the secret or service_role key: anything with these prefixes can be read by every visitor.
Do I need to restart anything after changing .env locally?
Yes. The Vite development server reads .env files when it starts, so stop it and run it again after editing them.

A blank page still returns 200 OK, so most uptime monitors say your site is up. Pingbuddy opens your app in a real browser and alerts you the moment visitors see a blank screen. Free for up to 20 sites.

Watch my site free →