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:
- Environment variables exist in the preview (or in your local
.env) but were never added on the production host. Variables withVITE_orNEXT_PUBLIC_are baked in at build time, so the build must run after they're set. - Supabase Auth URLs still point at
localhost. Sign-up confirmation emails, magic links and OAuth logins redirect to the Site URL or redirect URL you configured, so users land on a page that doesn't exist for them. - File name casing. macOS and Windows usually treat
Header.tsxandheader.tsxas the same file. Linux build servers don't, so an import with the wrong capitalization works locally and fails in production. - Asset paths or routing don't match the host (wrong
basepath, or no rewrite for client-side routes).
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:
- Netlify: Site configuration → Environment variables.
- Vercel: Project → Settings → Environment Variables (tick Production).
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:
- Set Site URL to your production address (for example
https://your-app.netlify.app), nothttp://localhost:3000. - Add your production URL, and any preview URLs you use, to Redirect URLs.
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
- If the console shows
404for/assets/...jsfiles, check that the host's publish directory is your build output (distfor Vite, handled automatically for Next.js on Vercel), and that Vite'sbasesetting matches where the site is served (usually/). - If the home page loads but refreshing
/dashboardgives a 404, add a rewrite. On Netlify, createpublic/_redirectswith/* /index.html 200.
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
- Invalid API key or undefined env vars on Vercel
- Why your v0 or Bolt app fails to deploy on Vercel
- Module not found: a checklist for AI-written code
- Supabase returns empty data with no error
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.