What Is a .env File? Format, Examples and Safety

A .env file is a plain text file of NAME=value lines that holds app settings and keys outside your code. It isn't encrypted, so keep it out of Git and off your live site.

Gary · Published · Updated · 7 min read

Four-step card titled What is a .env file?: NAME=value lines, keep it out of Git, the prefix decides what ships, secrets stay server-side.
On this page
  1. What is a .env file?
  2. What does the .env file format look like?
  3. How do you create a .env file?
  4. How do you use a .env file in Vite and Next.js?
  5. What's the difference between .env and .env.example?
  6. Which .env variables reach the browser?
  7. Should a .env file go in Git?
  8. How does a .env file end up public on a live site?
  9. What should you do if a key in your .env leaked?
  10. FAQ

Short answer: A .env file is a plain text file of NAME=value lines that holds your app's settings, such as database URLs and API keys, so they stay out of your code. Tools like Vite and Next.js read the env file when your app starts or builds. It's not encrypted, so it must stay out of Git and off your live site, and any variable with a public prefix (VITE_, NEXT_PUBLIC_) ends up in the browser.

By Gary, Greenlight · Last checked against the Vite, Next.js and Git docs: Oct 20, 2026 · Bundle test run by us on Oct 20, 2026 · Drafted with AI tools and reviewed before publishing.

What is a .env file?

A .env file ("dotenv" file) is a text file in your project folder that lists environment variables, one per line. The name starts with a dot, which hides it on Mac and Linux by default. Your code reads the values by name, so you can change a key or a URL without editing code, and use different values on your laptop and in production.

Vite says it uses the dotenv library to load these files (Vite docs (external)). Next.js loads .env* files into process.env for you (Next.js docs (external)).

What does the .env file format look like?

Each line is a name, an equals sign and a value. Lines that start with # are comments. Here is an env file example for a small app. Every value below is fake:

Bash

# Server-only: never sent to the browser
DATABASE_URL=postgres://app:fake-password@localhost:5432/app
STRIPE_SECRET_KEY=sk_test_FAKE_FAKE_FAKE

# Public: copied into the browser bundle at build time
VITE_SUPABASE_URL=https://example.supabase.co
VITE_APP_NAME="My App"

A few format rules people trip on:

  • Values are strings. Vite notes that VITE_SOME_KEY=123 comes back as the string "123", not a number (Vite docs (external)).
  • Quote values that contain spaces or #, like VITE_APP_NAME="My App" above. Plain values usually don't need quotes.
  • $ expands other variables in Vite, so write \$ when you mean a literal dollar sign (Vite docs (external)).
  • Restart after changes. Vite's docs say .env files are loaded at the start of Vite, so restart the server after editing (Vite docs (external)).

How do you create a .env file?

  1. In your project's root folder (next to package.json), create a file named exactly .env. No name before the dot, no .txt at the end. On Windows, turn on "File name extensions" in Explorer so it doesn't become .env.txt.
  2. Add one NAME=value per line.
  3. Add the file to .gitignore before your first commit (see below).
  4. Restart your dev server so it picks up the values.

From a terminal, touch .env (Mac/Linux) or ni .env (PowerShell) does step 1.

How do you use a .env file in Vite and Next.js?

Vite puts variables on import.meta.env. Only names starting with VITE_ reach your frontend code. The Vite docs show this with two lines: VITE_SOME_KEY=123 is visible in client code, DB_PASSWORD=foobar is undefined there (Vite docs (external)).

Next.js puts variables on process.env. Server code can read all of them. Only names starting with NEXT_PUBLIC_ are inlined into the JavaScript sent to the browser, and that happens at build time (Next.js docs (external)).

Both tools also load mode files. Vite reads .env, .env.local, .env.[mode] and .env.[mode].local, and its docs mark the .local ones as "ignored by git" (Vite docs (external)).

What's the difference between .env and .env.example?

.env holds real values and stays private. .env.example lists the same names with empty or fake values, and you do commit it, so a teammate (or future you) knows which variables the app needs:

Bash

# .env.example — safe to commit
DATABASE_URL=
STRIPE_SECRET_KEY=
VITE_SUPABASE_URL=

Which .env variables reach the browser?

This is the part most guides skip, and it's where AI-built apps leak keys. Anything with the public prefix is pasted into your built JavaScript as plain text. Vite's docs say VITE_* variables "should not contain sensitive information such as API keys" because they are "bundled into your source code at build time" (Vite docs (external)).

VariableVite appNext.js app
OPENAI_API_KEYserver onlyserver only
VITE_OPENAI_API_KEYin the browsernot special
NEXT_PUBLIC_OPENAI_API_KEYnot specialin the browser
VITE_SUPABASE_URL / publishable keyin the browser (fine, meant to be public)n/a

Try it yourself in two minutes. In a Vite project, add VITE_TEST_MARKER=hello-public and TEST_MARKER=hello-private to .env, log both in a component, run npm run build, then search the output:

Bash

grep -r "hello-public" dist/    # found: it's in your bundle
grep -r "hello-private" dist/   # nothing: it stayed out

We ran this test on Oct 20, 2026 with Vite 8.3.4 on Node 20.19.2: a two-line src/main.js that logs both variables, then npx vite build. The built file contained console.log(`hello-public`) and console.log(void 0). The public value was pasted in as plain text, and the private one was replaced with undefined. grep found hello-public in dist/assets/ and found nothing for hello-private.

That's the rule in one test: the prefix decides what ships. The Supabase anon or publishable key is designed to be public. See is my Supabase anon key safe?. A secret key is not. See Supabase service role key exposed?.

Should a .env file go in Git?

No. Add these lines to .gitignore before your first commit:

gitignore

.env
.env.*
!.env.example

Git's docs say a gitignore file covers "intentionally untracked files" and that "files already tracked by Git are not affected" (Git docs (external)). Next.js notes that its default create-next-app template already adds .env files to .gitignore (Next.js docs (external)). If you already committed .env, run git rm --cached .env, commit, and treat every key in it as leaked, because it's still in your history.

How does a .env file end up public on a live site?

Two common ways:

  1. The file itself is served. If .env lands in a folder your host serves (for example a public/ folder, or a whole project uploaded to a static host), anyone can request yoursite.com/.env and download it.
  2. A secret had a public prefix. The file is private, but a key named VITE_... or NEXT_PUBLIC_... was copied into the JavaScript every visitor downloads.

Hosts like Vercel and Netlify let you set variables in their dashboard instead of uploading a .env file at all. That's the safer pattern for production.

What should you do if a key in your .env leaked?

Revoke it with the provider and create a new one; deleting the file or commit is not enough. Our step-by-step guides: how to revoke an OpenAI API key, Claude API key security and rotating a Supabase service role key. If you build with AI tools, what is vibe coding? explains why secrets end up in frontend code so often. Before you launch, our Lovable launch checklist covers where secrets belong.

FAQ

Is a .env file safe? It's safe only while it stays on your machine or server. It isn't encrypted; anyone who gets the file can read every value.

Can people see my .env on a deployed site? Not if it's outside the served folder and your host doesn't serve dotfiles. They can always see any VITE_ or NEXT_PUBLIC_ value, because those are in your JavaScript.

What's .env.example for? It documents which variables the app needs, with no real values, so it's safe to commit.

Where do I put secrets in production? In your host's environment variable settings, read only by server code or serverless functions.

Sources

On this site

Related posts

Greenlight is independent and not affiliated with or endorsed by Vite, Vercel, Next.js, Netlify, Lovable, Supabase, Git, OpenAI or Anthropic. Product names are used only to identify the tools this guide is about. This page is general information, not professional security advice, legal advice, a security audit or a guarantee. Check your own setup against the vendor's current docs.