If you've cloned an open-source project from GitHub, you've probably seen these two files:
.env
.env.example
At first glance, they look similar, but they serve completely different purposes.
Let's understand the difference.
What is a .env file?
A .env file contains the actual environment variables that your application uses while running.
Example:
DATABASE_URL=postgres://user:password@localhost:5432/mydb
JWT_SECRET=mySuperSecretKey
API_KEY=abc123xyz
PORT=3000
These values are real secrets.
Your application reads them at runtime using libraries like:
-
dotenv(Node.js) -
python-dotenv(Python) - Framework-specific environment loaders
Why shouldn't you commit .env?
Because it contains sensitive information such as:
- Database credentials
- API keys
- JWT secrets
- OAuth client secrets
- Cloud service credentials
If someone gets access to these values, they may gain unauthorized access to your services.
That's why .env is usually added to .gitignore.
.env
What is a .env.example file?
A .env.example file is simply a template.
It shows other developers which environment variables are required, without exposing the actual values.
Example:
DATABASE_URL=
JWT_SECRET=
API_KEY=
PORT=3000
Or with placeholder values:
DATABASE_URL=your_database_url
JWT_SECRET=your_jwt_secret
API_KEY=your_api_key
PORT=3000
Notice that there are no real secrets.
Why do we need .env.example?
Imagine a new developer clones your project.
Without documentation, they have no idea which environment variables are required.
A .env.example solves this problem.
Instead of asking:
"What environment variables do I need?"
They can simply run:
cp .env.example .env
Then update the values.
Comparison
.env |
.env.example |
|---|---|
| Contains real values | Contains placeholder values |
| Used by the application | Used by developers as a template |
| Should not be committed | Safe to commit |
Usually listed in .gitignore
|
Usually tracked in Git |
| Contains secrets | Contains no secrets |
Typical Project Structure
project/
│
├── .env
├── .env.example
├── .gitignore
├── package.json
└── src/
.gitignore
node_modules/
.env
Workflow
- Clone the repository.
- Copy the example file.
cp .env.example .env
- Fill in the actual credentials.
- Start the application.
Every developer now has their own private .env file.
Best Practices
✅ Commit .env.example to your repository.
✅ Add .env to .gitignore.
✅ Never store production secrets in Git.
✅ Keep .env.example updated whenever a new environment variable is added.
✅ Use meaningful placeholder values instead of real credentials.
Example
.env
DATABASE_URL=postgres://admin:password123@localhost:5432/shop
JWT_SECRET=s8K@91aP!dX2
API_KEY=sk_live_xxxxxxxxxxxxxxxxx
.env.example
DATABASE_URL=your_database_url
JWT_SECRET=your_jwt_secret
API_KEY=your_api_key
Notice how the structure is identical, but the sensitive values are removed.
Final Thoughts
Think of these files like this:
-
.env= Your personal wallet (contains your real money and should stay private). -
.env.example= A checklist showing what belongs in the wallet (safe to share with everyone).
Following this practice makes your projects more secure, easier to onboard new developers, and more professional for open-source collaboration.
Top comments (0)