All guidesMore providers: databases, auth, hosting, email and payments
On this page

Render static site question

Render

Why are my VITE_ variables undefined on a Render static site?

By Ohad Krispin, founder of VibeRaven · LinkedIn

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 check

What 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.md

Why 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.co

Does 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

  1. 01
    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 check
  2. 02
    List every variable the client code reads:
    grep -rnoE "import\.meta\.env\.[A-Z0-9_]+" src
  3. 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.
  4. 04Save with "Save, rebuild, and deploy". "Save only" does not deploy, and "Save and deploy" reuses the old build.
  5. 05
    Check the build settings. The Vite deployment guide gives this build command and the dist publish directory:
    npm install && npm run build
  6. 06Add the names, with no values, to .env.example so the repo lists what the build needs.
  7. 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

Sources

Official docs behind this checklist

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.