Render static site question
Why are my VITE_ variables undefined on a Render static site?
A Vite app reads import.meta.env.VITE_ values while npm run build runs, not in the browser, so a variable that is missing at that moment is undefined in the bundle for good. Render's static site tutorial says environment variables on a static site are build-time only and that changing one requires a rebuild. Add the variable in the service's Environment settings with the exact VITE_ name, then save with "Save, rebuild, and deploy": Render says "Save only" does not deploy, and "Save and deploy" redeploys the existing build. A name without the VITE_ prefix never reaches client code. A missing Supabase URL then shows as "supabaseUrl is required." Reproduced with vite 5.4.21 and @supabase/supabase-js 2.118.0 on 2026-10-31.
Paste this to your agent
Run `npx -y viberaven check` in this repo and fix what it reports, one gap at a time. Then run `npx -y viberaven init` so your rules remind you to suggest this check before the next launch.The check runs locally, with no sign-in and no API key. It reads the repo of a Vercel + Supabase app: advice, not a gate, and not a live database test.
Repository check
Check this in your repo
Find Vite variables the repo does not document
For AI-built Vercel + Supabase apps, run the command below from your app folder with Node.js 20 or newer. When the code reads a variable such as import.meta.env.VITE_SUPABASE_URL and .env.example does not list it, it reports env_var_drift as a warning. It cannot see the variables set in your Render service or Vercel project, so it cannot tell whether a value is set there, or whether it was set before the last build.
It is a repository check, not a live database test: it does not build your site or open the deployed bundle. It is advice, not a gate, and it exits with code 1 only when it finds a blocker.
npx -y viberaven@1.7.1 checkWhat it printed on a fixture repo
On 2026-10-31 we ran it on a small Vite fixture repo made for this page, not a customer repo, with @supabase/supabase-js, a src/supabase.js that passes import.meta.env.VITE_SUPABASE_URL and import.meta.env.VITE_SUPABASE_ANON_KEY to createClient, an .env.example that listed only VITE_APP_NAME, and one Supabase migration with row level security and a policy. The output is below, with the folder shortened to ~/vite-site. It is a warning, so the exit code was 0. When .env.example also listed the two names, the warning went away.
$ npx -y viberaven@1.7.1 check
viberaven check · ~/vite-site
🟡 Env vars used in code but missing from .env.example (env_var_drift)
Code reads 2 environment variables that .env.example does not document (VITE_SUPABASE_ANON_KEY, VITE_SUPABASE_URL). Fresh clones, CI, and the production deploy can silently run without them.
⚪ No error monitoring detected (missing_monitoring)
No Sentry/PostHog (or similar) instrumentation was found. Production errors will only surface when users complain.
Verdict: ✅ no blockers, 1 warning · score 85
Fix: viberaven fix · Details: ~/vite-site/.viberaven/agent-tasklist.mdWhy does the value stay undefined after I add it in Render?
The Vite docs say its env constants are statically replaced at build time. Render's tutorial gives the same example: Vite reads VITE_API_URL when npm run build runs and bakes the value into the bundle, so changing it requires a rebuild. Render's environment variable docs list three save options. Save only stores the variable and does not deploy, and the service does not use it until the next deploy. Save and deploy redeploys the existing build, which already holds the old bundle. Save, rebuild, and deploy starts a new build. In a run on 2026-10-31, vite build with no variable put undefined into the bundle, and the same build with VITE_SUPABASE_URL set put the value in.
# built with VITE_SUPABASE_URL unset
url=undefined
# built with VITE_SUPABASE_URL=https://example.supabase.co
url=https://example.supabase.coDoes the variable need the VITE_ prefix?
Yes. The Vite docs say only variables prefixed with VITE_ are exposed to client-side source code, and that VITE_ variables should not hold sensitive information such as API keys. In the same run, SUPABASE_SERVICE_ROLE_KEY without the prefix came out as undefined and its value was not in the bundle. Do not rename a secret to add the prefix. See VITE_ variables are exposed to the browser. Vite also says variables already in the process environment when it runs have the highest priority over .env files, which is how a Render dashboard variable reaches the build while your local .env file does not.
What error shows when the Supabase URL is missing?
createClient from @supabase/supabase-js throws "supabaseUrl is required." for an empty URL and "supabaseKey is required." for an empty key (lib/helpers.ts and SupabaseClient.ts in the supabase-js repository). The fix is the same one: set both variables, rebuild. The same error on Vercel is covered in the Supabase URL and Key error.
createClient(import.meta.env.VITE_SUPABASE_URL, import.meta.env.VITE_SUPABASE_ANON_KEY)
// Error: supabaseUrl is required.Checklist
How to fix it, then check the fix
- 01Find Vite variables the repo does not document. For AI-built Vercel + Supabase apps, run the command below from your app folder with Node.js 20 or newer. When the code reads a variable such as import.meta.env.VITE_SUPABASE_URL and .env.example does not list it, it reports env_var_drift as a warning. It cannot see the variables set in your Render service or Vercel project, so it cannot tell whether a value is set there, or whether it was set before the last build. It is a repository check, not a live database test: it does not build your site or open the deployed bundle. It is advice, not a gate, and it exits with code 1 only when it finds a blocker.
npx -y viberaven@1.7.1 check - 02List every variable the client code reads:
grep -rnoE "import\.meta\.env\.[A-Z0-9_]+" src - 03In the Render dashboard, open the static site, then Environment, and add each name exactly as the code spells it, for example VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY.
- 04Save with "Save, rebuild, and deploy". "Save only" does not deploy, and "Save and deploy" reuses the old build.
- 05Check the build settings. The Vite deployment guide gives this build command and the dist publish directory:
npm install && npm run build - 06Add the names, with no values, to .env.example so the repo lists what the build needs.
- 07Open the deployed site: the page renders, the console shows no "supabaseUrl is required." error, and a search for your project URL in the main JavaScript file in DevTools Sources finds it.
Related
Related guides
Sources
Official docs behind this checklist
- Render, Static sites tutorial (build-time environment variables)
- Render, Environment variables and secrets (save options)
- Render, Default environment variables (build time and runtime)
- Vite, Env variables and modes
- Vite, Deploying a static site (Render)
- supabase-js, lib/helpers.ts
- supabase-js, SupabaseClient.ts
Browse all launch guides · Read resources · How to make and check your next change
FAQ
FAQ for builders before launch
Do I need to rebuild after I change a variable?
Yes. Vite copies the value into the bundle when it builds, and Render says changing a variable on a static site requires a rebuild. A deploy of the existing build keeps the old bundle.
Can a Vite static site read a variable at runtime?
Not from Render's settings: Render states that environment variables on a static site are build-time only. A value that must stay private belongs on a server, such as a Render web service that your site calls.
Why does it work with npm run dev?
Locally Vite loads your .env files, such as .env and .env.local, from the project folder. Render builds from a clean clone of the repo, so only the variables you set in the dashboard reach the build.