MMakerToLaunch

Guides

What Are Environment Variables?

If your AI-built app works on your laptop but breaks the moment you deploy, environment variables are often the reason. They are the invisible settings — API keys, database URLs, secret keys — that your app reads when it starts. This guide explains what they are, why you should never hardcode them, and exactly how to set them when you go live.

Updated July 2026 · 10 min read

Written for AI makers using tools like Cursor, Bolt, Lovable, Replit, Claude, and ChatGPT.

Quick answer

Environment variables are name–value pairs (like DATABASE_URL=postgres://…) that your app reads at runtime instead of baking secrets into code. Locally you store them in a .env file; in production you paste them into your hosting dashboard. Never commit real .env files to GitHub — use .env.example as a safe template instead.

Who this is for

  • You built an app with Cursor, Bolt, Lovable, or similar and see a .env file you do not fully understand
  • Your app works locally but fails after deploy with errors about missing keys or connection strings
  • You want to know what to put in Vercel, Railway, or Render before clicking Deploy

What you'll need

  • Your project folder open on your computer
  • A .env file or .env.example file (if your app has one)
  • Access to your hosting platform dashboard (Vercel, Railway, Render, etc.)

A simple definition

An environment variable is a setting stored outside your source code that your app reads when it runs. Instead of writing your database password directly in a Python or JavaScript file, you give the app a name like DATABASE_URL and tell the server what value that name should have.

Think of environment variables as sticky notes the computer reads before starting your app. On your laptop, those notes live in a file called .env. On a hosting platform, you type the same names and values into a settings page. The code stays identical — only the notes change between your machine and production.

This matters because code gets uploaded to GitHub, shared with collaborators, and stored in version history forever. Settings that must stay private — API keys, database passwords, signing secrets — should never be written directly into files you push online.

Real examples you will see

Every project names variables differently, but certain patterns appear again and again in AI-generated apps. Open your .env or .env.example file and look for names like these:

  • DATABASE_URL — tells Django, Rails, or Node where your PostgreSQL database lives
  • SECRET_KEY — used by Django and other frameworks to sign sessions and cookies
  • OPENAI_API_KEY or ANTHROPIC_API_KEY — connects your app to an AI provider
  • NEXT_PUBLIC_API_URL — a frontend variable pointing to your backend (the NEXT_PUBLIC_ prefix means browsers can read it)
  • STRIPE_SECRET_KEY — payment processing; must stay server-side only
  • DEBUG — often True locally and False in production

Frontend vs backend environment variables

Not all environment variables are treated the same. Backend variables stay on the server — users never see them. That is where you put database URLs, secret API keys, and signing tokens.

Frontend frameworks like Next.js and Vite can expose certain variables to the browser, but only if you follow naming rules. In Next.js, only variables prefixed with NEXT_PUBLIC_ are visible in client-side JavaScript. Everything else stays server-side.

A common beginner mistake is putting a secret key in a frontend variable because the AI tool needed it for a quick demo. If the variable name starts with NEXT_PUBLIC_ or VITE_, assume it is public. Move sensitive keys to API routes or server functions instead.

When in doubt, ask: 'Would I be okay if a stranger saw this value in their browser?' If no, it belongs in backend-only configuration.

Why you should not hardcode secrets

Hardcoding means writing a secret directly in your source code — like pasting your OpenAI key inside a JavaScript file. It feels fast during development, and AI tools sometimes do it for you without asking.

The problem is that Git remembers everything. Once you push a key to GitHub, it exists in commit history even if you delete it later. Bots scan public repos for exposed keys within minutes. Rotating a leaked key is stressful and can cost money.

Environment variables solve this by separating configuration from code. Your code says process.env.OPENAI_API_KEY or os.environ['OPENAI_API_KEY'] — the actual value comes from the environment at runtime, not from a file in your repo.

Even for solo projects, using environment variables builds the habit you need before sharing code or hiring help. It is the standard every professional team follows.

.env vs .env.example

Your .env file contains real values and lives only on your computer (and on your hosting platform's dashboard). It should never be committed to GitHub. Add .env to your .gitignore file so Git ignores it automatically.

A .env.example file is the safe version you do share on GitHub. It lists every variable name your app needs, usually with placeholder values like your-api-key-here or postgres://user:password@localhost:5432/dbname. Teammates, future you, and deployment tools use it as a checklist.

If your project has a .env file but no .env.example, create one before your first push. Copy the variable names, replace real values with placeholders, and commit only the example file. A launch readiness scan will flag a missing .env.example as a common blocker.

Some teams also use .env.local for machine-specific overrides. The rule stays the same: real secrets stay out of Git.

Setting variables on Vercel

Vercel is popular for Next.js and React frontends. After connecting your GitHub repo, open your project in the Vercel dashboard and go to Settings → Environment Variables.

Add each variable name exactly as it appears in your .env file — spelling and capitalization matter. DATABASE_URL and database_url are different variables to most frameworks. Paste the production value, then choose which environments apply: Production, Preview, and Development.

After adding or changing variables, redeploy your project. Existing deployments do not pick up new variables automatically. Click Deployments → the three dots on your latest deploy → Redeploy.

For Next.js apps, remember the NEXT_PUBLIC_ prefix rule. Server-only variables work in API routes and server components without any prefix.

Setting variables on Railway and Render

Railway and Render are common choices for Django, FastAPI, and full-stack Node apps. Both follow the same pattern: open your service, find the Variables or Environment tab, and add key–value pairs.

On Railway, creating a PostgreSQL database automatically adds DATABASE_URL to your project. You still need to add SECRET_KEY, ALLOWED_HOSTS, and any third-party API keys manually. Railway injects variables into your app at runtime — you do not need a .env file on the server.

Render works similarly. Go to your web service → Environment → Add Environment Variable. If you use a Render PostgreSQL instance, link it in the dashboard and Render sets DATABASE_URL for you.

For both platforms, trigger a new deploy after changing variables. If your app crashes immediately on startup, check the deploy logs — 'KeyError', 'undefined', or 'connection refused' often mean a missing or misspelled variable.

How your code actually reads them

In Node.js and Next.js, you access variables with process.env.VARIABLE_NAME. In Python and Django, use os.environ.get('VARIABLE_NAME') or django-environ. In Vite frontends, import.meta.env.VITE_VARIABLE_NAME.

AI-generated projects often include a library like dotenv that loads your local .env file automatically when you run npm run dev or python manage.py runserver. In production, the hosting platform sets variables directly — no .env file is needed on the server.

If your app crashes with 'environment variable X is not defined', search your codebase for that name. Then check your local .env and your hosting dashboard to make sure the name matches exactly.

Step-by-step

  1. 1

    Step 1

    Find what your app expects

    Open .env.example or search your code for process.env, os.environ, and import.meta.env. List every variable name.

  2. 2

    Step 2

    Secure your local .env

    Confirm .env is in .gitignore. Never push it. Create or update .env.example with placeholder values only.

  3. 3

    Step 3

    Copy values to your host

    In Vercel, Railway, or Render, add each variable with the same name and your production value. Use production API keys, not test keys, when going live.

  4. 4

    Step 4

    Redeploy and test

    Trigger a fresh deploy. Open your live URL and walk through the main user flow. Check host logs if anything fails.

Common mistakes

  • Committing .env to GitHub

    How to fix it: Add .env to .gitignore, remove it from Git history if already pushed, rotate any exposed keys, and commit only .env.example.

  • Typo in variable name on the host

    How to fix it: Variable names are case-sensitive. Copy names exactly from .env.example — do not retype from memory.

  • Forgetting to redeploy after adding variables

    How to fix it: Most hosts require a new deploy for changes to take effect. Redeploy from the dashboard after every env change.

  • Using localhost URLs in production

    How to fix it: Replace http://localhost:3000 with your real production API URL in hosting environment variables.

  • Putting secrets in NEXT_PUBLIC_ or VITE_ variables

    How to fix it: Move sensitive keys to server-side code or API routes. Only expose truly public values to the browser.

Copy-ready prompt

Prompt: create safe .env.example files

Paste this into Cursor, Claude, ChatGPT, Bolt, Lovable, or your AI coding tool.

Ready to paste

Review my project and create a safe .env.example file.

1. Search the codebase for all environment variable usage (process.env, os.environ, import.meta.env, django-environ, etc.).
2. List every variable name the app expects.
3. Create or update .env.example with placeholder values only — no real secrets.
4. Confirm .env is listed in .gitignore and not tracked by Git.
5. For each variable, add a one-line comment explaining what it is for.
6. Flag any secrets currently hardcoded in source files and suggest moving them to environment variables.

Do not include real API keys, passwords, or connection strings in any file that would be committed to GitHub.

Paste this into Cursor, Claude, ChatGPT, Bolt, Lovable, or your AI coding tool.

Ready check

Beginner checklist

  • Listed all environment variables your app reads at startup
  • Created .env.example with placeholder values (no real secrets)
  • Confirmed .env is in .gitignore and not on GitHub
  • Copied every variable name and production value to your hosting dashboard
  • Verified names match exactly (case-sensitive) between local and host
  • Redeployed after setting variables
  • Tested main flows on the live URL

Frequently asked questions

What is the difference between .env and .env.example?
.env holds real secrets and stays on your machine and hosting dashboard only. .env.example is a template with fake placeholder values that you commit to GitHub so everyone knows which variables to configure.
Why does my app work locally but not after deploy?
Your local .env file does not travel to GitHub or your host automatically. You must manually add the same variable names and production values in your hosting platform's environment settings, then redeploy.
Can I share my .env file with a collaborator?
Share values through a secure channel (password manager, encrypted message) — never through GitHub or email. Give them .env.example from the repo and share real values separately.
Do I need different values for staging and production?
Often yes. Use separate API keys and database instances for production. Most hosts let you set different variable values per environment (Production vs Preview on Vercel, for example).
What if my AI tool created a .env file with real keys?
Treat those keys as potentially exposed if you ever pushed them. Rotate the keys with the provider, move values to a local-only .env, create .env.example with placeholders, and run a safe-upload check before pushing to GitHub.