Works in Preview, Blank Page in Production: How to Fix It

Quick answer: App works in preview but shows a blank page on Netlify or Vercel? Check missing env vars, Supabase redirect URLs set to localhost, and case-sensitive imports.

The error

The app works in your AI tool's preview or on localhost, but the live site shows a blank white page, or login sends you to localhost:3000. Open the browser DevTools console (F12 → Console) on the live site. You'll usually see one of these:

Uncaught Error: supabaseUrl is required.
Uncaught TypeError: Cannot read properties of undefined (reading 'VITE_API_URL')
Failed to load resource: the server responded with a status of 404 (/assets/index-abc123.js)
Could not resolve "./components/Header" from "src/App.tsx"   (in the build log)

A single uncaught error while the app starts can stop React from rendering anything, which is why the page is completely blank instead of showing an error.

Why it happens

Your preview and your production host are different environments:

Fixes

1. Read the first error in the console and the build log

Open the live site, press F12, and reload. The first red error is the one that matters. Also open the latest deploy log on Netlify or Vercel and check for warnings or errors. To reproduce production on your own machine, run a production build instead of the dev server:

npm run build && npm run preview   # Vite
npm run build && npm start         # Next.js

2. Add the environment variables on your host and redeploy

Copy every variable your app needs from your local .env (or your AI tool's settings) into the host:

Then trigger a new deploy. Changing a variable doesn't update a site that's already built. Browser code can only read variables with the right prefix (VITE_ for Vite, NEXT_PUBLIC_ for Next.js). Never put secret keys behind those prefixes, because they end up in the JavaScript every visitor downloads.

3. Point Supabase Auth at your real domain

In the Supabase dashboard, go to Authentication → URL Configuration:

In code, don't hard-code localhost. Build redirect links from the current address:

await supabase.auth.signInWithOtp({
  email,
  options: { emailRedirectTo: `${window.location.origin}/auth/callback` },
});

The same applies to redirectTo in signInWithOAuth. Confirmation emails that were already sent still contain the old link, so test with a fresh sign-up.

4. Fix case-sensitive imports

Make every import match the file name exactly, letter for letter:

import Header from './components/Header';   // file must be Header.tsx, not header.tsx

If you need to rename a file only by case, Git on macOS/Windows may not notice the change. Rename it through Git so the new casing is committed:

git mv src/components/header.tsx src/components/Header.tsx
git commit -m "Fix file name casing"

5. Check asset paths and client-side routes

6. Add an error boundary so failures aren't silent

Wrap your app in a React error boundary that shows a friendly "Something went wrong" message. Next time a production-only error happens, users see a message instead of a blank page, and you get a clearer clue.

Prompt to paste into your AI tool

My app works in preview but the production deploy shows a blank page. Here is the first console error from the live site: [paste it]. List every environment variable the app reads, tell me which ones must be set on my host (and which must NOT be public), check that all imports match file-name casing exactly, and make sure Supabase auth redirects use window.location.origin instead of localhost. Don't change unrelated code.

FAQ

Why does it work in Lovable or Bolt's preview? The preview runs in the builder's own environment, which may already have your variables and settings. Your Netlify or Vercel site only knows what you configure there.

I added the env vars and it's still blank. Make sure you deployed again after adding them, that the names match exactly (including the prefix), and that there are no quotes or trailing spaces in the values.

Login emails still go to localhost. Update the Site URL and Redirect URLs in Supabase, then send a new email. Links in old emails won't change.

Related guides

Still stuck? Paste your exact error into the free Error Fixer to get a plain-English cause, the fix, and a prompt to paste back into your AI tool.

Get the free "10 Prompts That Fix Broken AI Code" pack

Join the UnbreakKit newsletter: one short email a week with real errors from Cursor, Lovable, Bolt & Replit users and how to fix them. Unsubscribe anytime.

Newsletter signup powered by beehiiv. We only use your email to send the newsletter.