Skip to content

Guides

Your app works in preview but shows a blank page in production

Niall Hackett ·

A blank (white or black) page after deploying almost always means one JavaScript error stopped React from rendering at all. The host still serves the page with a 200 OK, which is why nothing looks broken on the hosting dashboard. In apps built with Lovable, Bolt, Cursor or Replit on Vite + Supabase, the most common cause is environment variables that exist in the builder but were never set on the production host.

Step 1: Read the first error

  1. Open your live URL in an incognito window. Being logged in to your builder can hide the problem.
  2. Open DevTools (F12) → Console, then reload with the console already open.
  3. Look at the first red error. Typical messages:
    • supabaseUrl is required
    • Invalid URL or a request going to undefined/rest/v1/...
    • Cannot read properties of undefined
  4. Check the Network tab for anything red (404 on a .js or .css file).

If the error mentions supabase or undefined, carry on to step 2. If it's a 404 on an asset, skip to step 4.

Step 2: Add the env vars on the host

Vite only exposes variables that start with VITE_ to the browser, and it bakes them in at build time.

  1. Find the variable names your app uses: check .env.example or search the code for import.meta.env..
  2. Add them on your host:
    • Vercel: Project → Settings → Environment Variables. Tick Production (and Preview if you use it).
    • Netlify: Site configuration → Environment variables.
    • Lovable hosting: these are normally injected for you. If they've gone missing after a failed build, reconnect Supabase and republish.
  3. Typical Supabase pair: VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY (or VITE_SUPABASE_ANON_KEY).
  4. Redeploy. Adding a variable doesn't change a build that already exists.

Never put the Supabase service_role key in a VITE_ variable. Anything prefixed VITE_ ends up publicly readable in your JS bundle.

Step 3: Make it fail loudly next time

Add a guard where the Supabase client is created:

TypeScript
const url = import.meta.env.VITE_SUPABASE_URL;
const key = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY;
if (!url || !key) throw new Error("Missing Supabase env vars in this build");

A clear message in the console beats a silent blank page.

Step 4: Check build settings and routing

  • Build command: npm run build. Output/publish directory: dist.
  • Home page works but other URLs show blank or a 404: add SPA fallback routing.
    • Netlify: a public/_redirects file containing /* /index.html 200
    • Vercel: a rewrite to /index.html in vercel.json

Step 5: Confirm the fix

Reload in incognito, check the console is clean, and click through your main pages. Test on a phone as well.


Run a free ReplayWatch scan. Paste your live URL and ReplayWatch checks it for page load, security headers, secrets exposed in your HTML/JS, Supabase/Firebase data that is readable without login, broken links and assets, SEO tags, and whether your signup page is reachable. It does not log in or run your signup flow. → https://replaywatch.com/#scan