# Environment Variables: Where Settings and Secrets Live

> What environment variables are, why you need a .env file, why values differ between development and production, and why secrets never go in the frontend.

Published: 2026-08-26 · Source: https://subxcat.com/articles/environment-variables · Author: SUBXCAT

Environment variables are settings an app receives from outside when it starts, instead of keeping them in its code: the database address, API keys, the mode it runs in. The same code reads them and behaves differently depending on where it is running.

If you've seen a `.env` file in your project or lines like `process.env.DATABASE_URL`, that's them. Here is why they exist, how they work and where vibe-coded projects most often get them wrong.

## Why environment variables exist

Imagine the database address is written straight into the code. Then:

- switching from the production database to a test one means editing code;
- the database password ends up in Git and stays in the history forever, even if you delete it later;
- anyone with access to the repository has access to the data.

Environment variables separate two things: **what the program does** (code, identical everywhere) and **what it works with** (settings, specific to each place it runs). You can safely show the code to a contractor or make it public, while the settings stay with whoever runs it.

## The .env file and how it works

On a server, variables are set in the hosting dashboard or the launch configuration. Locally it's easier to keep them in a `.env` file at the project root, which your framework or a library reads on startup.

```
DATABASE_URL=postgres://localhost:5432/myapp
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_API_URL=http://localhost:3000
```

Three rules for this file:

- `.env` always goes in `.gitignore`. Check it now, not later.
- Next to it sits `.env.example` with the same names and no real values. That one is in Git, and it tells a new person what needs filling in.
- If a `.env` with real keys ever reached the repository, treat those keys as leaked. Rotate them; deleting the file isn't enough.

## Why values differ in each environment

A normal project runs in at least two places: your computer and production. Often there's also staging, a copy for checking things before release. The code is the same everywhere; the variables are not:

- locally, a test database and test payment keys;
- on staging, a separate database with fake data;
- in production, the real database and live keys that only the server knows.

That way a stray run on your laptop won't charge a real card or email real customers. If your local `.env` holds live keys, you're in exactly the situation environment variables are supposed to prevent.

## The big trap: environment variables in the frontend

This is where people get confused most. Server-side environment variables stay on the server. Frontend variables, however, are **written straight into the JavaScript** the browser downloads at build time. After that, any visitor can read them in developer tools.

Frameworks mark these with a prefix: `NEXT_PUBLIC_`, `VITE_`, `REACT_APP_`, `EXPO_PUBLIC_`. The prefix doesn't mean "handy variable". It means "this string will be public".

What's fine to expose with that prefix:

- the URL of your API;
- a public analytics or maps key;
- the public Supabase or Firebase key, which is designed to be seen; your access rules protect the data, not the key.

What never belongs there:

- secret payment keys;
- keys for OpenAI, Anthropic and other paid APIs;
- service-level database keys that bypass access rules;
- passwords, email service tokens, signing keys.

If the frontend needs something that requires a secret, such as calling an AI model, the request goes through your server or a server function. The browser asks your server, and the server, holding the secret, calls the external API.

## A couple more subtleties

- **Variables are read at startup or at build time.** Changed a value in the hosting dashboard? Restart the app, and often rebuild the frontend. Otherwise you'll spend an hour wondering why nothing changed.
- **An empty value is worse than an error.** If a required variable is missing, the app should fail at startup with a clear message rather than run with a blank key.
- **Don't log variables wholesale.** "Let me print the config for debugging" is a common way secrets end up in logs.

## In short

- Environment variables are settings an app gets at startup rather than keeping in code.
- `.env` stays out of Git; `.env.example` without values goes in.
- Development, staging and production have different values, and live keys exist only on the server.
- Anything prefixed `NEXT_PUBLIC_`, `VITE_` and the like ships to the browser and becomes public.
- After changing a variable, restart or rebuild the app.

If you're not sure which keys have already made it into your bundle, SUBXCAT can check and sort it out.
