All guidesCheck your own repo
On this page

Vercel question

Vercel

Which env vars does my app read that are missing in Vercel production?

By Ohad Krispin, founder of VibeRaven · LinkedIn

List every name the code reads with git grep for process.env and import.meta.env, then compare that list with vercel env ls production: a name in the first list and not in the second is missing, and a NEXT_PUBLIC_ or VITE_ name you add needs a new deployment, because both frameworks copy those values in at build time. Names read with Deno.env.get belong to Supabase Edge Functions, so check those with supabase secrets list, not in Vercel.

Next step in your repo: run npx -y viberaven@1.6.12 check. It lists the names your code reads that .env.example or a similar template does not document as env_var_drift; it cannot see the variables set in Vercel, so compare its list with vercel env ls production.

Paste this to your agent

Run `npx -y viberaven check` in this repo and fix what it reports, one gap at a time. Also check that every env var name the code reads is set in vercel env ls production. 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

List the names the code reads and no template documents

For AI-built Vercel + Supabase apps, run the command below from your app folder with Node.js 20 or newer. It collects the names read through process.env, import.meta.env, Deno.env.get and similar calls, compares them with .env.example, .env.sample and other templates, and reports the ones no template lists as env_var_drift; it cannot see the variables set in Vercel, so it gives you the names most likely to be missing there, and you compare them with vercel env ls production. It leaves out names the platforms set themselves, such as NODE_ENV and VERCEL_ names, and the default secrets of Supabase Edge Functions such as SUPABASE_URL.

It is a repository check, not a live database test: it reads files and sends nothing to Vercel. It is advice, not a gate, and it exits with code 1 when it finds a blocker.

npx -y viberaven@1.6.12 check

What it printed on a fixture repo

On 2026-10-28 we ran it on a small Vite fixture repo made for this page, not a customer repo. src/lib/analytics.ts reads VITE_POSTHOG_KEY and VITE_POSTHOG_HOST, supabase/functions/send-email/index.ts reads RESEND_API_KEY and SUPABASE_URL, and .env.example lists only the Supabase URL and publishable key. SUPABASE_URL was left out as an Edge Function default. The output is below, with the folder shortened to ~/app. The finding is a warning, so the exit code was 0.

$ npx -y viberaven@1.6.12 check

viberaven check · ~/app

🟡 Env vars used in code but missing from .env.example  (env_var_drift)
   Code reads 3 environment variables that .env.example does not document (RESEND_API_KEY, VITE_POSTHOG_HOST, VITE_POSTHOG_KEY). Fresh clones, CI, and the production deploy can silently run without them.

Verdict: ✅ no blockers, 1 warning · score 90
Fix: viberaven fix · Details: ~/app/.viberaven/agent-tasklist.md

List the names your code reads

These searches print each name once. They cover the dot form, process.env.NAME and import.meta.env.NAME; also search for process.env[ if your code reads names with brackets.

# Next.js and Vite code
git grep -ohE "(process|import.meta).env.[A-Z][A-Z0-9_]+" | awk -F. '{print $NF}' | sort -u

# Supabase Edge Functions (these live in Supabase, not Vercel)
git grep -ohE "Deno.env.get..[A-Z][A-Z0-9_]+" -- supabase/functions | sort -u

Compare them with Vercel production

vercel env ls production lists the names set for Production without printing the values. The loop below prints each name the code reads that the list lacks. Skip the names Vercel and the frameworks set themselves, such as NODE_ENV and the VERCEL_ system variables, which Vercel fills in automatically.

vercel env ls production > /tmp/vercel-production.txt
for name in $(git grep -ohE "(process|import.meta).env.[A-Z][A-Z0-9_]+" | awk -F. '{print $NF}' | sort -u); do
  grep -qw "$name" /tmp/vercel-production.txt || echo "not in Vercel production: $name"
done

Set and still undefined

Vercel's docs say a change to environment variables applies only to new deployments, not to earlier ones. A NEXT_PUBLIC_ or VITE_ value is copied into the JavaScript during the build, so redeploy after you add or change one. Check the scope too: a variable set for Preview only is missing in Production. See the Vercel env vars checklist.

Names read in Supabase Edge Functions

A name read with Deno.env.get runs in Supabase, so setting it in Vercel does nothing. List what the project has with supabase secrets list, and set a missing one with supabase secrets set NAME=value. SUPABASE_URL, SUPABASE_DB_URL and the key variables are provided to every function, so they never need setting.

Checklist

Find and fix missing production variables

  1. 01Run the searches above and save the list of names the code reads.
  2. 02Compare it with vercel env ls production, and the Edge Function names with supabase secrets list.
  3. 03
    Add each missing name for Production, then redeploy so the build picks it up:
    vercel env add NAME production
    vercel --prod
  4. 04Add every name to .env.example with a placeholder value, so the next clone and the next check see it.

Related

Sources

Official docs behind this checklist

FAQ

FAQ for builders before launch

Can I pull production values to my machine to compare?

vercel env pull --environment=production writes them to a local file, and Secret values Vercel cannot read come back as placeholders. You rarely need the values: vercel env ls lists the names, which is enough to find what is missing.

Why does the app work locally and fail on Vercel?

Locally the framework reads your .env.local file, which is not deployed. Every name in it has to be set again in the Vercel project.