Start From a Working .env Template, Not a Blank File
Pick the variables your project actually needs, database, auth, cloud storage, whatever applies, and get a correctly formatted .env file back with the naming conventions those services expect.
- Skip searching for variable names
- Grouped by category
- Matches naming conventions services expect
Why use a generator?
A hand-typed .env file tends to drift: a variable named one way in this project and a different way in the next, a database URL missing the port because you copied it from memory. A generator keeps the naming consistent across every project you start.
Whether you're bootstrapping something new or bringing an old project's configuration up to a standard, picking from known-good variable names beats retyping them each time.
Before you use the file
- 1Add
.envto.gitignorebefore it holds anything real - 2Commit a
.env.examplecopy with placeholders so teammates know what's required - 3Replace every placeholder with a real value before you run the project
- 4Split into
.env.localand.env.productiononce the values start to differ by environment
Understanding Variable Categories
What each category is for and when you need it
Database Configuration
Anything that persists data needs these, and getting the connection string format wrong is the single most common reason a fresh checkout fails to start.
The connection string for your primary database. The format changes with the database:
- PostgreSQL: postgres://user:pass@host:5432/dbname
- MySQL: mysql://user:pass@host:3306/dbname
- MongoDB: mongodb+srv://user:pass@cluster.mongodb.net/dbname
Connection string for Redis, typically used for caching, sessions, and rate limiting. Format: redis://user:pass@host:6379
Authentication & Security
These variables sign tokens and cookies, which makes them the ones worth generating properly instead of typing a memorable string.
A random string used to sign JSON Web Tokens or session cookies. At least 32 characters of real randomness, generated with:
openssl rand -base64 32Required by NextAuth.js/Auth.js: the canonical URL of your site (e.g., https://example.com). Use http://localhost:3000 in development.
API Keys & External Services
Each third-party service invents its own key format and naming convention, which is exactly why a template beats remembering them.
Stripe splits these in two: a secret key (sk_*) for server-side calls and a publishable key (pk_*) for the client. The secret key should never reach the browser.
Your OpenAI key for GPT models, embeddings, and other API calls. Starts with sk-. Billing and rate limits are tied to this one key.
Email service keys for transactional email and notifications sent from your backend.
Cloud Storage & CDN
Variables for file uploads, static assets, and content delivery.
AWS IAM credentials for S3, CloudFront, and similar services. Create a dedicated IAM user scoped to only what the app needs rather than reusing a root key.
A single URL bundling your Cloudinary credentials and cloud name, used for image transformation and delivery.
Application Configuration
General settings that control runtime behavior and environment detection.
Indicates development, production, or test. Plenty of libraries change behavior, logging verbosity included, based on this single value.
The port your server listens on. Defaults vary by framework (3000 for Next.js, 5000 for Flask), and most hosts set this automatically.
In Next.js, anything prefixed NEXT_PUBLIC_ ships to the browser bundle. Use it for values the client genuinely needs, never for a secret.
Framework-Specific Setup
How five common frameworks load these variables
Next.js
Next.js loads .env files automatically based on the current environment, no extra package needed.
NEXT_PUBLIC_ reach client-side code. Everything else stays server-only.Express.js
Express doesn't load .env files on its own; you need the dotenv package.
Vite
Vite supports .env out of the box, with its own prefix convention instead of NEXT_PUBLIC_.
VITE_ are exposed to client-side code.Create React App
CRA requires the REACT_APP_ prefix for any variable it exposes.
Django / Flask (Python)
Python projects typically reach for python-dotenv or django-environ.
Keeping Each Variable Type Safe
The habits that matter most for each category above
Database Credentials
Use a separate database user for each environment, scoped to only the permissions it needs, and require SSL/TLS on every production connection. Never reuse development credentials in production, and keep them out of error messages and logs, since both tend to end up somewhere more public than intended.
API Keys
Give development, staging, and production their own keys, set usage alerts and rate limits on each, and rotate them on a schedule, especially after someone leaves the team. Never put a secret key where client-side code can read it; use the service's publishable key there instead.
Authentication Secrets
Generate secrets with a cryptographically secure method (openssl rand -base64 32), and give each application and environment its own. Skip predictable values like "secret" even in development, and never share a JWT secret across unrelated apps.
Cloud Storage Credentials
Create a dedicated IAM user or role per application with minimal permissions, prefer temporary credentials or IAM roles where the platform supports them, and enable MFA delete on any S3 bucket holding sensitive data. Root account credentials don't belong in application code.