My site wouldn't publish. The error log showed font warnings and a cryptic exit code, and I spent way too long looking at the wrong thing.
Here's what actually happened, and the fix that took two minutes once I understood it.
The error
❌ Missing VITE_SUPABASE_URL or VITE_SUPABASE_PUBLISHABLE_KEY in .env
error: script "build" exited with code 1The build log also showed a bunch of warnings about font files:
NataSans-Regular.woff2 didn't resolve at build time
NataSans-Bold.woff2 didn't resolve at build timeThose font warnings look alarming. They are not the problem. They just mean the fonts live in public/fonts/ and get resolved at runtime, which is correct. Ignore them completely.
What was actually happening
My project has a custom prerender script (scripts/prerender.mjs) that runs after the normal Vite build. It does something important for SEO:
- Spins up a local server with the freshly built
dist/folder - Opens a headless browser (Puppeteer)
- Visits every route (home, /blog, each post, each thought)
- Saves the fully rendered HTML to disk
Why this matters: when Google, Twitter, LinkedIn, or WhatsApp visit your site, many of them don't execute JavaScript. If you only serve the empty index.html that React generates, they see a blank page. Prerendering gives them complete HTML with titles, meta tags, and content, so your links look good when shared and your pages get indexed properly.
To know which routes to prerender, the script queries Supabase for the list of published blog posts and thoughts. And to connect to Supabase, it needs two variables:
VITE_SUPABASE_URLVITE_SUPABASE_PUBLISHABLE_KEY
Why it broke
The script reads those variables from a .env file. On my machine, that file exists, so local builds work fine. But in Lovable's build environment, there is no .env file. The variables either get injected differently or aren't available to post-build Node scripts at all.
The script couldn't find the variables, called process.exit(1), and the entire build failed. That's it. That's the whole mystery.
The fix
In scripts/prerender.mjs, I changed the strict check to fallbacks with hardcoded values:
const supabaseUrl =
env.VITE_SUPABASE_URL ||
process.env.VITE_SUPABASE_URL ||
'https://your-project-ref.supabase.co';
const supabaseAnonKey =
env.VITE_SUPABASE_PUBLISHABLE_KEY ||
process.env.VITE_SUPABASE_PUBLISHABLE_KEY ||
'your-anon-key-here';The priority order:
| Source | When it works |
|---|---|
.env file | Local development |
process.env | CI/CD pipelines |
| Hardcoded fallback | Safety net so the build never fails |
.env file
Local development
process.env
CI/CD pipelines
Hardcoded fallback
Safety net so the build never fails
Is it safe to hardcode those keys?
Yes. The VITE_SUPABASE_PUBLISHABLE_KEY (anon key) is public by design:
- It already travels to the browser on every page visit. Anyone can see it in DevTools > Network.
- Your
src/integrations/supabase/client.tsprobably already has the same fallback pattern. - The actual security of your database depends on Row Level Security (RLS) policies on your tables, not on hiding this key.
What you never hardcode: the service_role key. That one is full admin access. It should only live in Edge Functions as a secret, never in client code or build scripts.
The general lesson
When a build script depends on environment variables, you have three options:
| Option | When to use |
|---|---|
| Fail hard if the var is missing | Private secrets (Stripe secret key, API tokens) |
| Hardcode a fallback | Public values (Supabase URL, anon key, project IDs) |
| Configure the var in the build environment | Cleanest, but requires platform support |
Fail hard if the var is missing
Private secrets (Stripe secret key, API tokens)
Hardcode a fallback
Public values (Supabase URL, anon key, project IDs)
Configure the var in the build environment
Cleanest, but requires platform support
For Supabase URL and anon key in a Lovable project, the fallback is the most pragmatic choice. The build always works and you're not exposing anything that wasn't already public.
If you have a prerender script too
If you've added prerendering or any custom post-build script to your Lovable project and it needs Supabase access, paste this prompt:
"In my prerender script, check if the Supabase environment variables have hardcoded fallbacks. If they don't, add my project URL and anon key as fallbacks so the build doesn't fail when .env isn't available. Keep the env var references as the primary source, just add || fallback values."
You can find your project URL and anon key in the Supabase dashboard under Settings > API, or in the Lovable Cloud panel.
Quick reference
| Symptom | Cause | Fix |
|---|---|---|
| Build fails with "Missing VITE_SUPABASE_URL" | Post-build script can't read .env | Add hardcoded fallbacks |
| Font warnings in build log | Fonts in public/ resolved at runtime | Ignore, not an error |
| Build works locally but fails on publish | .env exists locally but not in Lovable's build | Same fix, add fallbacks |
Build fails with "Missing VITE_SUPABASE_URL"
Post-build script can't read .env
Add hardcoded fallbacks
Font warnings in build log
Fonts in public/ resolved at runtime
Ignore, not an error
Build works locally but fails on publish
.env exists locally but not in Lovable's build
Same fix, add fallbacks
One more silent publish blocker
The env var fallback above is the version of this that bit me. The other one I keep seeing in the community: a leftover test database from Lovable's old test/live beta. If you ever turned that on, a stray "test" db can sit attached to your project and block your publish for weeks, with no error that points at it. The preview works, the publish just won't go.
The fix is to delete the test database in Lovable Cloud > database, then republish. I wrote that one up on its own here: The Silent Test Database That Blocks Your Lovable Publish.
And if your publish is failing with TRANSIENT_INFRA or executor.GetLogs ... connection refused and you never used test/live, that's the build executor being unreachable on the platform side, not your code. Retry a couple times spaced out, and if it stays stuck for a day or more, email support@lovable.dev with your project id and the exact error line so they can reset your build state.