Guides
Best Practices
Recommended practices for managing environment variables with EnvWizard
Environment Variable Best Practices
This guide covers recommended practices for managing environment variables in your projects using EnvWizard.
General Principles
1. Security First
- Never commit
.envfiles containing sensitive information to version control - Use
.gitignoreto exclude.envfiles:.env*(but not.env.example) - Rotate secrets regularly and after team member departures
- Use different variables for different environments (development, staging, production)
2. Consistency and Clarity
- Use descriptive names that clearly indicate purpose
- Follow consistent naming conventions
- Document all variables in
.env.examplewith comments - Group related variables together
3. Validation and Type Safety
- Use EnvWizard's validation features to ensure required variables exist
- Generate TypeScript types for environment variables
- Add runtime validation for critical variables
Naming Conventions
Recommended Format
CATEGORY_SUBCATEGORY_NAME=valueExamples
# ✅ Good examples
DATABASE_URL=postgres://localhost:5432/mydb
API_KEY_STRIPE=sk_test_123456
FEATURE_FLAG_DARK_MODE=true
# ❌ Poor examples
DB=postgres://localhost:5432/mydb # Too vague
stripeKey=sk_test_123456 # Inconsistent casing
DarkMode=true # Not descriptive enoughCommon Categories
APP_- Application-specific settingsDATABASE_- Database connectionsAPI_KEY_- External service API keysFEATURE_FLAG_- Feature togglesSMTP_- Email service configuration
File Organization
Standard Files
.env- Local development variables (never committed).env.example- Template with keys but no sensitive values (committed).env.test- Variables for test environment.env.staging- Variables for staging environment.env.production- Variables for production environment (never committed)
Example File Structure
# .env.example
# Database Configuration
DATABASE_URL= # URL to the database
DATABASE_USERNAME= # Database username
DATABASE_PASSWORD= # Database password
# API Keys
API_KEY_STRIPE= # Stripe payment processing
API_KEY_SENDGRID= # Email delivery service
# Application Settings
APP_URL=http://localhost:3000 # Base application URL
APP_PORT=3000 # Port the app runs on
DEBUG=false # Enable debug modeEnvWizard Workflow
Setup Phase
- Create initial
.envfile for development - Run
env-mage initto generate.env.example - Add comments and organize variables in
.env.example - Run
env-mage typegento generate TypeScript types - Commit
.env.exampleand generated type files
Development Phase
- Run
env-mage validatebefore starting development - Use
env-mage scanto track variable usage - Run
env-mage lintto maintain consistent formatting - Update
.env.examplewhen adding new variables
Deployment Phase
- Run
env-mage diffto compare environments - Use
env-mage syncto align environment files - Run
env-mage validate --strictto ensure all required variables exist
Environment Variables in Different Frameworks
Next.js
- Prefix public variables with
NEXT_PUBLIC_ - Use
.env.localfor local overrides - Set up per-environment variables with
.env.development,.env.production
React with Vite
- Prefix variables with
VITE_ - Access variables with
import.meta.env.VITE_VARIABLE
Node.js/Express
- Load variables early in the application bootstrap
- Validate critical variables before server startup
Continuous Integration
- Set up CI checks to validate
.env.exampleagainst required variables - Run
env-mage validatein CI pipeline with a CI-specific env file - Add
env-mage scanto detect unused variables
Pre-commit Hooks
Use Husky and lint-staged to set up pre-commit hooks:
// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,ts,jsx,tsx}": ["env-mage scan --quiet"],
".env.example": ["env-mage lint --quiet"]
}
}Type Safety
Runtime Validation
Combine EnvWizard's types with runtime validation:
// env-validation.ts
import { z } from "zod";
import "env.types.ts"; // Generated by EnvWizard
const envSchema = z.object({
DATABASE_URL: z.string().url(),
API_KEY: z.string().min(10),
PORT: z.string().regex(/^\d+$/).transform(Number),
DEBUG: z.enum(["true", "false"]).transform((val) => val === "true"),
});
export function validateEnv() {
const parsed = envSchema.safeParse(process.env);
if (!parsed.success) {
console.error("❌ Invalid environment variables:");
console.error(parsed.error.format());
process.exit(1);
}
return parsed.data;
}
// Use the validated environment
export const env = validateEnv();Secrets Management
For production environments, consider:
-
Using a secrets manager like:
- AWS Secrets Manager
- Google Cloud Secret Manager
- HashiCorp Vault
- Azure Key Vault
-
Integrating with EnvWizard:
# Pull secrets into .env.production (never committed) ./scripts/pull-secrets.sh # Validate the environment env-mage validate --env .env.production --strict
Conclusion
Following these best practices will help you maintain secure, consistent, and reliable environment variables across your projects. EnvWizard's suite of tools makes implementing these practices easier and more automated, reducing the chance of errors and security issues related to environment configuration.