Why are my environment variables undefined after I deploy my AI-built app?
Your environment variables are undefined after deployment because Vercel does not automatically import your local .env file. You must add each variable manually in the Vercel dashboard under Settings → Environment Variables, then redeploy. If the variable is accessed by browser-side code (not a server function), the name must start with NEXT_PUBLIC_ for Next.js apps or VITE_ for Vite apps. Variables added after a build only take effect on the next deployment, so a redeploy is required even if the dashboard shows them correctly.
Drafted with AI assistance and checked by automated quality and compliance review before publishing.
How do you check whether your variables are actually missing?
Open your Vercel dashboard, select your project, go to Settings, then Environment Variables. If the variables your code expects are not listed there, that is why they are undefined.
The fastest confirmation is comparing what Vercel has against what your code references.
- In the Vercel dashboard, open your project and click Settings → Environment Variables.
- Note every variable name listed and its environment scope (Production, Preview, Development).
- In your codebase, search for
process.env.(Next.js) orimport.meta.env.(Vite). List every variable name your code tries to read. - Any name in step 3 that is missing from step 2 will be
undefinedat runtime.
Also check spelling and casing. SUPABASE_URL is not the same as SUPABASE_url. Environment variable names are case-sensitive.
If the variable is listed but your app still cannot read it, the scope may be wrong. A variable scoped only to Preview will be undefined in Production. Click the variable row to confirm it includes the environment where your app is deployed.
Why do AI tools leave environment variables behind at deployment?
AI coding tools generate code that references variables, but they cannot push those variables into your hosting dashboard. The .env.local file on your machine stays on your machine.
When Lovable, Bolt, Cursor or another AI tool writes code that calls process.env.STRIPE_SECRET_KEY, it assumes a variable by that name exists. Locally, you create a .env.local file, paste in the key, and everything works. The tool never told Vercel about that variable because it has no access to your Vercel account.
Vercel builds run on remote servers. Those servers start fresh with only what your repository contains (your code) plus what the dashboard supplies (environment variables). The .env.local file is typically excluded from Git by your .gitignore, which is correct: secrets should not be committed. But that also means the build machine has no way to know the value.
This is not a bug in the AI tool. It is a deliberate separation between local secrets and deployed secrets. The gap only becomes visible when you deploy.
The preview-to-production jump
Some AI tools deploy to their own preview URLs first, where they inject variables on your behalf. When you connect a custom domain or push to Vercel separately, those injected values do not carry over. The app breaks on deploy because the production environment is not the same as the AI tool's preview sandbox.
How do you add environment variables correctly in Vercel?
In the Vercel dashboard, go to Settings → Environment Variables, add each name and value, select all environments that need it, then redeploy.
Follow these steps for each variable your app requires:
- Open vercel.com, sign in, and select your project.
- Click Settings in the top navigation, then Environment Variables in the left sidebar.
- In the Key field, enter the variable name exactly as your code references it (for example,
SUPABASE_SERVICE_ROLE_KEY). - In the Value field, paste the secret. Vercel encrypts it at rest.
- Under Environment, check the boxes for Production, Preview and Development, unless you have a reason to restrict it.
- Click Save.
Repeat for every variable. Common ones for AI-built apps:
SUPABASE_URLandSUPABASE_ANON_KEY(orSUPABASE_SERVICE_ROLE_KEYfor server functions)OPENAI_API_KEYSTRIPE_SECRET_KEYandSTRIPE_PUBLISHABLE_KEYDATABASE_URLif using a direct Postgres connection
Redeploy to pick up the new values
Variables you add do not affect deployments that already finished. You must trigger a new build.
- Go to the Deployments tab.
- Find the most recent Production deployment.
- Click the three-dot menu and choose Redeploy.
- Confirm.
Once the new deployment finishes, your environment variables will be present at build time.
What is the NEXT_PUBLIC_ prefix and when do you need it?
Next.js exposes environment variables to browser code only if their names start with NEXT_PUBLIC_. Without that prefix, the variable exists on the server but reads as undefined in the browser.
Next.js compiles two bundles: one for the server and one for the browser. Server-side code can read any environment variable. Browser-side code can only see variables whose names begin with NEXT_PUBLIC_.
If your code runs in a React component that executes in the browser and reads process.env.SUPABASE_ANON_KEY, that variable will be undefined unless you rename it to NEXT_PUBLIC_SUPABASE_ANON_KEY both in Vercel and in your code.
How to decide which prefix to use
| Where does the code run? | Variable prefix | Example | |--------------------------|-----------------|----------| | Server function, API route, getServerSideProps | No prefix required | SUPABASE_SERVICE_ROLE_KEY | | Browser-side React component | NEXT_PUBLIC_ | NEXT_PUBLIC_SUPABASE_ANON_KEY |
Never expose a secret key to the browser. The service_role key or any SECRET_KEY must stay on the server. If you add NEXT_PUBLIC_ to a secret, anyone viewing your site can read it.
Vite apps use a different prefix
If your AI tool generated a Vite app instead of Next.js, the prefix is VITE_ instead of NEXT_PUBLIC_. Variables without that prefix are not replaced during the Vite build and will be undefined in the browser bundle.
What does this fix not cover?
Adding environment variables correctly solves the undefined-at-deploy problem. It does not fix secrets already leaked into your repository, runtime errors unrelated to missing variables, or mismatched database schemas.
Secrets committed to Git
If an AI tool wrote a secret directly into your source code, or if you accidentally committed .env.local, adding the variable to Vercel does not undo the exposure. The secret is in your repository's history. Rotate that key immediately in its provider dashboard (Stripe, OpenAI, Supabase), then update the new value in Vercel. For guidance on checking whether this happened, see Is my secret key exposed in the browser?.
Variables that exist but are wrong
A variable can be defined and still cause failures if the value is incorrect: a truncated API key, a staging URL pointing at production, or a connection string missing the password. Compare the value in Vercel against the original source.
Database or schema problems
An app that throws errors after deploy may be talking to an empty database, a database with outdated migrations, or a database behind a firewall that blocks Vercel's IP range. Environment variables being present is necessary but not sufficient for the app to work.
Variables read only at build time
Some frameworks bake environment variables into the JavaScript bundle during build, not at request time. If you change a variable in Vercel and hit Redeploy, the new build picks it up. But if you expect a running deployment to read a new value without a rebuild, it will not. Vercel edge functions and serverless routes can read variables at request time; static pages cannot.
When does this stop being a do-it-yourself job?
If your environment variables are set correctly, your app still fails, and the error logs point to authentication, database connections, or access control, the issue is deeper than a missing variable.
Signs the problem has grown past environment configuration:
- Vercel's function logs show authentication errors even though the keys are present.
- Your Supabase dashboard shows policy violations or RLS denials.
- The app works for some users but returns empty data for others.
- You see 500 errors but no clear message in the logs about which variable or service failed.
These symptoms usually mean the code expects a different authentication flow, the database schema is out of sync, or row-level security policies block the queries the code is running. Fixing them requires reading the server logs, understanding the database policies, and adjusting either the code or the schema.
If you have set every variable, redeployed, confirmed the values are correct, and the app still breaks, a second person who can read the logs and the database policies will save you time. For apps that need to move from an AI-generated draft to a production state, finishing the last mile involves more than configuration: it is the architecture, the error handling and the data model the AI tool left incomplete.
Start with the $1,500 Rapid Diagnostic.
Related reading.
The rescue playbook.
Real prompts, security rules, and teardowns of broken AI-built apps, sent when we publish something worth your inbox. No fluff, no drip sequence.
One or two emails a month. Unsubscribe anytime.
Still seeing undefined after you've set everything?
If the variables are present but your app still fails, the problem is in the code or database layer. A written diagnostic shows where the real break is.
Common questions about Vercel environment variables
Should I commit my .env.local file to Git so Vercel can read it?
No. Committing secrets to a repository exposes them to anyone with read access, and the values stay in Git history even if you delete the file later. The correct approach is adding variables through the Vercel dashboard, which encrypts them at rest and never exposes them in your source code.
Can I copy all my local .env variables to Vercel automatically?
Vercel's CLI can push a local .env file with the command vercel env pull to download or vercel env add to upload one variable at a time. There is no single command to bulk-import a file, but you can script it. Always review what you are uploading to avoid pushing test values into production.
My app works in Vercel Preview but fails in Production. Why?
Check that every environment variable is scoped to Production, not just Preview. In the Vercel dashboard, click each variable and confirm the Production checkbox is selected. Also confirm the Production deployment was triggered after the variables were added; otherwise it is running on stale values.
How do I know if a variable is build-time or runtime?
In Next.js, variables read inside getStaticProps or at the top level of a module are build-time. Variables read inside API routes, server actions, or getServerSideProps are runtime. Vite variables are always build-time. Changing a build-time variable requires a redeploy; runtime variables take effect on the next request.
Why does my AI tool keep hardcoding secrets instead of using environment variables?
AI models generate code that works immediately in the conversation. They do not always know your deployment target or secret management policy. After the tool writes a line like const key equals your actual key, you must replace it with process.env.YOUR_KEY, add the real value to your .env.local locally and to Vercel for production.