env-configuration
Apply when managing application configuration: environment variables, secrets management, and config validation.
When & Why to Use This Skill
This Claude skill provides a comprehensive framework for managing application configurations, focusing on environment variables, secrets management, and automated validation. By leveraging 12-factor app principles and Zod-based schema validation, it helps developers build secure, scalable, and error-resistant systems while preventing sensitive data leaks and runtime configuration errors.
Use Cases
- Establishing a secure and standardized environment file structure (.env, .env.local, .env.example) for multi-stage deployment workflows.
- Implementing 'fail-fast' configuration validation using Zod to ensure all required environment variables are present and correctly formatted before the application starts.
- Securing Next.js applications by correctly separating server-side secrets from public client-side variables using the NEXT_PUBLIC_ prefix logic.
- Automating the creation of .gitignore rules and template files to prevent accidental exposure of sensitive API keys and database credentials in version control.
| name | env-configuration |
|---|---|
| description | Apply when managing application configuration: environment variables, secrets management, and config validation. |
| version | 1.0.0 |
| tokens | ~550 |
| confidence | high |
| - https | //nextjs.org/docs/app/building-your-application/configuring/environment-variables |
| last_validated | 2025-01-10 |
| next_review | 2025-01-24 |
| tags | [configuration, environment, security, devops] |
When to Use
Apply when managing application configuration: environment variables, secrets management, and config validation.
Patterns
Pattern 1: Environment File Structure
# Source: https://12factor.net/config
# .env.example (commit this - template without secrets)
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
REDIS_URL=redis://localhost:6379
API_KEY=your-api-key-here
NODE_ENV=development
# .env.local (DO NOT COMMIT - actual secrets)
DATABASE_URL=postgres://prod:secret@prod-db:5432/myapp
API_KEY=sk_live_abc123
# .env.development / .env.production (environment defaults)
NEXT_PUBLIC_API_URL=http://localhost:3000/api
LOG_LEVEL=debug
Pattern 2: Zod Validation at Startup
// Source: https://zod.dev/
// src/config/env.ts
import { z } from 'zod';
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url().optional(),
API_KEY: z.string().min(1),
PORT: z.coerce.number().default(3000),
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
});
// Validate on import - fails fast at startup
export const env = envSchema.parse(process.env);
// Type-safe access throughout app
console.log(env.DATABASE_URL); // string (validated)
Pattern 3: Next.js Environment Variables
// Source: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables
// NEXT_PUBLIC_ prefix = exposed to browser
// Without prefix = server-only
// .env.local
DATABASE_URL=secret // Server only
NEXT_PUBLIC_API_URL=/api // Available in browser
// Usage in code
// Server component/API route
const dbUrl = process.env.DATABASE_URL;
// Client component
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
Pattern 4: Config Object Pattern
// Source: Best practice pattern
// src/config/index.ts
import { env } from './env';
export const config = {
isDev: env.NODE_ENV === 'development',
isProd: env.NODE_ENV === 'production',
server: {
port: env.PORT,
host: env.HOST || '0.0.0.0',
},
database: {
url: env.DATABASE_URL,
poolSize: env.DB_POOL_SIZE || 10,
},
auth: {
jwtSecret: env.JWT_SECRET,
tokenExpiry: '1h',
},
features: {
enableBeta: env.ENABLE_BETA_FEATURES === 'true',
},
} as const;
// Usage
import { config } from '@/config';
if (config.features.enableBeta) { /* ... */ }
Pattern 5: .gitignore for Env Files
# Environment files
.env
.env.local
.env.*.local
.env.development.local
.env.production.local
# Keep example
!.env.example
Pattern 6: Required vs Optional
// Source: https://zod.dev/
const envSchema = z.object({
// Required - app won't start without these
DATABASE_URL: z.string().url(),
JWT_SECRET: z.string().min(32),
// Optional with defaults
PORT: z.coerce.number().default(3000),
LOG_LEVEL: z.string().default('info'),
// Optional without default
SENTRY_DSN: z.string().url().optional(),
// Conditional (required in production)
REDIS_URL: z.string().url().optional()
.refine(
(val) => process.env.NODE_ENV !== 'production' || val,
'REDIS_URL required in production'
),
});
Anti-Patterns
- Hardcoded secrets - Always use environment variables
- Secrets in .env.example - Only placeholder values
- No validation - Fail fast with Zod at startup
- NEXT_PUBLIC_ for secrets - Exposes to browser
Verification Checklist
- .env.example committed with placeholders
- .env.local in .gitignore
- Zod validation at app startup
- Secrets not prefixed with NEXT_PUBLIC_
- Required vs optional clearly defined