Why your Lovable app fails to deploy (and how to fix it)
Your Lovable app works perfectly in the preview. Then you export it to GitHub, connect Vercel or Netlify, and get a red build log. Here are the six causes we see most often, in the order you should check them.
1. Environment variables aren't set on the host
Lovable injects your Supabase keys automatically, but your host doesn't. Vite only exposes variables prefixed with VITE_, and it inlines them at build time. If you add them after the build has run, you need to redeploy.
VITE_SUPABASE_URL=https://xyz.supabase.co VITE_SUPABASE_ANON_KEY=eyJhbGciOi...
Add them in the Vercel or Netlify project settings for every environment (Production and Preview), then trigger a fresh deploy.
2. TypeScript errors the preview ignored
The dev server is forgiving, but tsc in a production build isn't. Run npm run build locally. Fix string | undefined errors with real null checks rather than as any.
3. Case-sensitive imports
macOS doesn't care about ./Components/Button versus ./components/button, but Linux build servers do. Make your import paths match the file names exactly.
4. Missing or mismatched lockfile
If there's both a bun.lockb and a package-lock.json, the host may pick the wrong package manager. Keep one lockfile, commit it, and set the install command explicitly.
5. SPA routes return 404
The deploy "succeeds", but refreshing /dashboard gives a 404. React Router needs a rewrite to index.html:
// vercel.json
{ "rewrites": [{ "source": "/(.*)", "destination": "/" }] }
# netlify: public/_redirects
/* /index.html 200
6. Node version drift
Pin the Node version with "engines": {"node": "20.x"} in package.json so the host matches your local setup.
A quick checklist
- Does
npm run buildpass locally? - Are all
VITE_*variables set on the host for every environment? - Is there one lockfile, committed?
- Do import paths match file names exactly?
- Is the SPA rewrite configured?
- Is the Node version pinned?