Environment Management
> **Skill Purpose:** Multi-environment configuration and deployment patterns
SKILL.md
Full skill instructions
Environment Management
Skill Purpose: Multi-environment configuration and deployment patterns
Core Skill Pattern
Objective: Establish consistent environment management across development, staging, and production deployments.
Universal Pattern:
- Define environment hierarchy (dev/staging/prod)
- Create environment-specific configurations
- Establish configuration validation
- Set up deployment environment mapping
- Create environment-specific build processes
Key Decisions (Project-Specific):
- Number and type of environments needed
- Configuration format and structure
- Environment variable management approach
- Deployment platform integration
- Build and deployment triggers
Project-Specific Implementation Notes
Customize per project:
- Environment count based on project complexity
- Configuration schema based on application needs
- Security requirements for each environment
- Integration with existing deployment infrastructure
- Team workflow and access patterns
Example Implementation (Next.js Multi-Environment Pattern)
Note: This is an example pattern. Adapt environments and configurations based on your specific project requirements.
Prerequisites (Example)
- Project initialized
- Basic environment variable structure
- Deployment platform selected
Example: Next.js Multi-Environment Implementation
Framework-Specific Example: This demonstrates the pattern using Next.js environments. Adapt for your tech stack and deployment needs.
1. Create Environment Structure
# Create environment directories
mkdir -p environments/{development,staging,production}
mkdir -p config/{environments,scripts}
# Create environment-specific files
touch environments/development/.env.development
touch environments/staging/.env.staging
touch environments/production/.env.production
# Create configuration files
touch config/environments/development.json
touch config/environments/staging.json
touch config/environments/production.json
2. Create Environment Configuration Schema
Create config/environments/schema.json:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Environment name"
},
"description": {
"type": "string",
"description": "Environment description"
},
"domain": {
"type": "string",
"format": "uri",
"description": "Environment domain URL"
},
"apiUrl": {
"type": "string",
"format": "uri",
"description": "API base URL"
},
"database": {
"type": "object",
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "Database connection URL"
},
"poolSize": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Database connection pool size"
}
},
"required": ["url"]
},
"features": {
"type": "object",
"properties": {
"analytics": {
"type": "boolean",
"description": "Enable analytics tracking"
},
"debug": {
"type": "boolean",
"description": "Enable debug mode"
},
"logging": {
"type": "boolean",
"description": "Enable logging"
},
"monitoring": {
"type": "boolean",
"description": "Enable monitoring"
}
}
},
"security": {
"type": "object",
"properties": {
"corsOrigins": {
"type": "array",
"items": {
"type": "string",
"format": "uri"
},
"description": "Allowed CORS origins"
},
"rateLimiting": {
"type": "object",
"properties": {
"max": {
"type": "integer",
"minimum": 1
},
"windowMs": {
"type": "integer",
"minimum": 1000
}
}
}
}
},
"deployment": {
"type": "object",
"properties": {
"platform": {
"type": "string",
"enum": ["vercel", "netlify", "aws", "docker"],
"description": "Deployment platform"
},
"buildCommand": {
"type": "string",
"description": "Build command"
},
"outputDirectory": {
"type": "string",
"description": "Build output directory"
}
}
}
},
"required": ["name", "domain", "apiUrl"]
}
3. Create Development Environment Configuration
Create config/environments/development.json:
{
"name": "development",
"description": "Local development environment",
"domain": "http://localhost:3000",
"apiUrl": "http://localhost:3000/api",
"database": {
"url": "postgresql://postgres:password@localhost:5432/zeus_dev",
"poolSize": 5
},
"features": {
"analytics": false,
"debug": true,
"logging": true,
"monitoring": false
},
"security": {
"corsOrigins": ["http://localhost:3000", "http://localhost:3001"],
"rateLimiting": {
"max": 1000,
"windowMs": 60000
}
},
"deployment": {
"platform": "local",
"buildCommand": "npm run build",
"outputDirectory": ".next"
}
}
4. Create Staging Environment Configuration
Create config/environments/staging.json:
{
"name": "staging",
"description": "Staging environment for testing",
"domain": "https://staging.zeus-framework.dev",
"apiUrl": "https://staging-api.zeus-framework.dev",
"database": {
"url": "postgresql://postgres:[email protected]:5432/zeus_staging",
"poolSize": 10
},
"features": {
"analytics": true,
"debug": true,
"logging": true,
"monitoring": true
},
"security": {
"corsOrigins": ["https://staging.zeus-framework.dev", "https://staging-admin.zeus-framework.dev"],
"rateLimiting": {
"max": 500,
"windowMs": 60000
}
},
"deployment": {
"platform": "vercel",
"buildCommand": "npm run build",
"outputDirectory": ".next"
}
}
5. Create Production Environment Configuration
Create config/environments/production.json:
{
"name": "production",
"description": "Production environment",
"domain": "https://zeus-framework.dev",
"apiUrl": "https://api.zeus-framework.dev",
"database": {
"url": "postgresql://postgres:[email protected]:5432/zeus_prod",
"poolSize": 20
},
"features": {
"analytics": true,
"debug": false,
"logging": true,
"monitoring": true
},
"security": {
"corsOrigins": ["https://zeus-framework.dev", "https://admin.zeus-framework.dev"],
"rateLimiting": {
"max": 100,
"windowMs": 60000
}
},
"deployment": {
"platform": "vercel",
"buildCommand": "npm run build",
"outputDirectory": ".next"
}
}
6. Create Environment Manager
Create config/environments/manager.ts:
import fs from 'fs';
import path from 'path';
export interface EnvironmentConfig {
name: string;
description: string;
domain: string;
apiUrl: string;
database: {
url: string;
poolSize: number;
};
features: {
analytics: boolean;
debug: boolean;
logging: boolean;
monitoring: boolean;
};
security: {
corsOrigins: string[];
rateLimiting: {
max: number;
windowMs: number;
};
};
deployment: {
platform: string;
buildCommand: string;
outputDirectory: string;
};
}
export class EnvironmentManager {
private static instance: EnvironmentManager;
private configs: Map<string, EnvironmentConfig> = new Map();
private currentEnvironment: string;
private constructor() {
this.loadConfigurations();
this.currentEnvironment = this.detectEnvironment();
}
static getInstance(): EnvironmentManager {
if (!EnvironmentManager.instance) {
EnvironmentManager.instance = new EnvironmentManager();
}
return EnvironmentManager.instance;
}
private detectEnvironment(): string {
const nodeEnv = process.env.NODE_ENV;
const vercelEnv = process.env.VERCEL_ENV;
if (vercelEnv) {
return vercelEnv === 'production' ? 'production' : 'staging';
}
switch (nodeEnv) {
case 'production':
return 'production';
case 'test':
return 'staging';
case 'development':
default:
return 'development';
}
}
private loadConfigurations(): void {
const configDir = path.join(process.cwd(), 'config', 'environments');
if (!fs.existsSync(configDir)) {
throw new Error(`Environment config directory not found: ${configDir}`);
}
const configFiles = fs.readdirSync(configDir).filter(file => file.endsWith('.json'));
for (const file of configFiles) {
const configPath = path.join(configDir, file);
const configName = file.replace('.json', '');
try {
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
this.configs.set(configName, config);
} catch (error) {
console.warn(`Failed to load environment config: ${configName}`, error);
}
}
}
getConfig(environment?: string): EnvironmentConfig {
const env = environment || this.currentEnvironment;
const config = this.configs.get(env);
if (!config) {
throw new Error(`Environment configuration not found: ${env}`);
}
return config;
}
getCurrentEnvironment(): string {
return this.currentEnvironment;
}
setCurrentEnvironment(environment: string): void {
if (!this.configs.has(environment)) {
throw new Error(`Unknown environment: ${environment}`);
}
this.currentEnvironment = environment;
}
getAllEnvironments(): string[] {
return Array.from(this.configs.keys());
}
validateConfig(config: EnvironmentConfig): boolean {
// Basic validation
if (!config.name || !config.domain || !config.apiUrl) {
return false;
}
// Validate URLs
try {
new URL(config.domain);
new URL(config.apiUrl);
new URL(config.database.url);
} catch {
return false;
}
return true;
}
getEnvironmentVariables(environment?: string): Record<string, string> {
const config = this.getConfig(environment);
return {
NEXT_PUBLIC_ENVIRONMENT: config.name,
NEXT_PUBLIC_APP_URL: config.domain,
NEXT_PUBLIC_API_URL: config.apiUrl,
NEXT_PUBLIC_ANALYTICS_ENABLED: config.features.analytics.toString(),
NEXT_PUBLIC_DEBUG_MODE: config.features.debug.toString(),
NEXT_PUBLIC_LOGGING_ENABLED: config.features.logging.toString(),
NEXT_PUBLIC_MONITORING_ENABLED: config.features.monitoring.toString(),
DATABASE_URL: config.database.url,
DATABASE_POOL_SIZE: config.database.poolSize.toString(),
CORS_ORIGINS: config.security.corsOrigins.join(','),
RATE_LIMIT_MAX: config.security.rateLimiting.max.toString(),
RATE_LIMIT_WINDOW_MS: config.security.rateLimiting.windowMs.toString(),
};
}
generateEnvFile(environment?: string): string {
const envVars = this.getEnvironmentVariables(environment);
return Object.entries(envVars)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
}
compareEnvironments(env1: string, env2: string): {
same: boolean;
differences: Record<string, { env1: any; env2: any }>;
} {
const config1 = this.getConfig(env1);
const config2 = this.getConfig(env2);
const differences: Record<string, { env1: any; env2: any }> = {};
const compareObjects = (obj1: any, obj2: any, prefix = '') => {
const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
for (const key of keys) {
const fullKey = prefix ? `${prefix}.${key}` : key;
const val1 = obj1[key];
const val2 = obj2[key];
if (typeof val1 === 'object' && typeof val2 === 'object' && val1 && val2) {
compareObjects(val1, val2, fullKey);
} else if (val1 !== val2) {
differences[fullKey] = { env1: val1, env2: val2 };
}
}
};
compareObjects(config1, config2);
return {
same: Object.keys(differences).length === 0,
differences,
};
}
}
// Export singleton instance
export const environmentManager = EnvironmentManager.getInstance();
7. Create Environment Utilities
Create src/lib/environment.ts:
import { environmentManager, type EnvironmentConfig } from '@/config/environments/manager';
export function getCurrentEnvironment(): string {
return environmentManager.getCurrentEnvironment();
}
export function getEnvironmentConfig(environment?: string): EnvironmentConfig {
return environmentManager.getConfig(environment);
}
export function isDevelopment(): boolean {
return getCurrentEnvironment() === 'development';
}
export function isStaging(): boolean {
return getCurrentEnvironment() === 'staging';
}
export function isProduction(): boolean {
return getCurrentEnvironment() === 'production';
}
export function isTest(): boolean {
return process.env.NODE_ENV === 'test';
}
export function getEnvironmentVariable(key: string, environment?: string): string | undefined {
const config = getEnvironmentConfig(environment);
// Map common environment variable names
const envVarMap: Record<string, keyof EnvironmentConfig> = {
'APP_URL': 'domain',
'API_URL': 'apiUrl',
'DATABASE_URL': 'database.url',
};
const configKey = envVarMap[key];
if (configKey) {
const keys = configKey.split('.');
let value: any = config;
for (const k of keys) {
value = value?.[k];
}
return value;
}
return process.env[key];
}
export function getFeatureFlags(environment?: string) {
const config = getEnvironmentConfig(environment);
return config.features;
}
export function isFeatureEnabled(feature: keyof EnvironmentConfig['features'], environment?: string): boolean {
const features = getFeatureFlags(environment);
return features[feature];
}
export function getDatabaseConfig(environment?: string) {
const config = getEnvironmentConfig(environment);
return config.database;
}
export function getSecurityConfig(environment?: string) {
const config = getEnvironmentConfig(environment);
return config.security;
}
export function getDeploymentConfig(environment?: string) {
const config = getEnvironmentConfig(environment);
return config.deployment;
}
// Client-side hook
export function useEnvironment() {
const config = getEnvironmentConfig();
const currentEnv = getCurrentEnvironment();
return {
environment: currentEnv,
config,
isDevelopment: currentEnv === 'development',
isStaging: currentEnv === 'staging',
isProduction: currentEnv === 'production',
features: config.features,
domain: config.domain,
apiUrl: config.apiUrl,
};
}
8. Create Environment Scripts
Create scripts/environment-manager.js:
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// ANSI color codes
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36c',
magenta: '\x1b[35m',
};
function colorLog(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
class EnvironmentScriptManager {
constructor() {
this.configDir = path.join(process.cwd(), 'config', 'environments');
this.envDir = path.join(process.cwd(), 'environments');
}
validateEnvironment(env) {
const configPath = path.join(this.configDir, `${env}.json`);
if (!fs.existsSync(configPath)) {
colorLog(`❌ Environment config not found: ${configPath}`, 'red');
return false;
}
try {
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
// Basic validation
if (!config.name || !config.domain || !config.apiUrl) {
colorLog(`❌ Invalid environment config: missing required fields`, 'red');
return false;
}
colorLog(`✅ Environment config is valid: ${env}`, 'green');
return true;
} catch (error) {
colorLog(`❌ Failed to validate environment config: ${env}`, 'red');
colorLog(error.message, 'red');
return false;
}
}
generateEnvFile(env) {
const configPath = path.join(this.configDir, `${env}.json`);
const envPath = path.join(this.envDir, `.env.${env}`);
if (!fs.existsSync(configPath)) {
colorLog(`❌ Environment config not found: ${configPath}`, 'red');
return false;
}
try {
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
// Ensure environment directory exists
if (!fs.existsSync(this.envDir)) {
fs.mkdirSync(this.envDir, { recursive: true });
}
// Generate environment file content
const envContent = this.generateEnvContent(config);
fs.writeFileSync(envPath, envContent);
colorLog(`✅ Generated environment file: ${envPath}`, 'green');
return true;
} catch (error) {
colorLog(`❌ Failed to generate environment file: ${env}`, 'red');
return false;
}
}
generateEnvContent(config) {
const envVars = {
'NEXT_PUBLIC_ENVIRONMENT': config.name,
'NEXT_PUBLIC_APP_URL': config.domain,
'NEXT_PUBLIC_API_URL': config.apiUrl,
'NEXT_PUBLIC_ANALYTICS_ENABLED': config.features.analytics,
'NEXT_PUBLIC_DEBUG_MODE': config.features.debug,
'NEXT_PUBLIC_LOGGING_ENABLED': config.features.logging,
'NEXT_PUBLIC_MONITORING_ENABLED': config.features.monitoring,
'DATABASE_URL': config.database.url,
'DATABASE_POOL_SIZE': config.database.poolSize,
'CORS_ORIGINS': config.security.corsOrigins.join(','),
'RATE_LIMIT_MAX': config.security.rateLimiting.max,
'RATE_LIMIT_WINDOW_MS': config.security.rateLimiting.windowMs,
};
return Object.entries(envVars)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
}
listEnvironments() {
colorLog('📋 Available Environments:', 'magenta');
colorLog('========================', 'magenta');
if (!fs.existsSync(this.configDir)) {
colorLog('❌ Environment config directory not found', 'red');
return;
}
const configFiles = fs.readdirSync(this.configDir).filter(file => file.endsWith('.json'));
for (const file of configFiles) {
const envName = file.replace('.json', '');
const configPath = path.join(this.configDir, file);
const envPath = path.join(this.envDir, `.env.${envName}`);
const hasConfig = fs.existsSync(configPath);
const hasEnvFile = fs.existsSync(envPath);
const configStatus = hasConfig ? '✅' : '❌';
const envStatus = hasEnvFile ? '✅' : '❌';
colorLog(`${configStatus} ${configPath}`, hasConfig ? 'green' : 'red');
colorLog(`${envStatus} ${envPath}`, hasEnvFile ? 'green' : 'red');
colorLog('', 'reset');
}
}
compareEnvironments(env1, env2) {
const config1Path = path.join(this.configDir, `${env1}.json`);
const config2Path = path.join(this.configDir, `${env2}.json`);
if (!fs.existsSync(config1Path) || !fs.existsSync(config2Path)) {
colorLog('❌ One or both environment configs not found', 'red');
return false;
}
try {
const config1 = JSON.parse(fs.readFileSync(config1Path, 'utf8'));
const config2 = JSON.parse(fs.readFileSync(config2Path, 'utf8'));
colorLog(`🔍 Comparing environments: ${env1} vs ${env2}`, 'blue');
const differences = this.findDifferences(config1, config2);
if (Object.keys(differences).length === 0) {
colorLog('✅ Environments are identical', 'green');
} else {
colorLog('⚠️ Differences found:', 'yellow');
Object.entries(differences).forEach(([key, values]) => {
colorLog(` ${key}:`, 'cyan');
colorLog(` ${env1}: ${JSON.stringify(values.env1)}`, 'yellow');
colorLog(` ${env2}: ${JSON.stringify(values.env2)}`, 'yellow');
});
}
return true;
} catch (error) {
colorLog('❌ Failed to compare environments', 'red');
return false;
}
}
findDifferences(obj1, obj2, prefix = '') {
const differences = {};
const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
for (const key of keys) {
const fullKey = prefix ? `${prefix}.${key}` : key;
const val1 = obj1[key];
const val2 = obj2[key];
if (typeof val1 === 'object' && typeof val2 === 'object' && val1 && val2) {
const nestedDifferences = this.findDifferences(val1, val2, fullKey);
Object.assign(differences, nestedDifferences);
} else if (val1 !== val2) {
differences[fullKey] = { env1: val1, env2: val2 };
}
}
return differences;
}
run() {
const args = process.argv.slice(2);
const command = args[0] || 'list';
const env = args[1];
switch (command) {
case 'validate':
if (!env) {
colorLog('❌ Environment name required', 'red');
colorLog('Usage: npm run env:validate <environment>', 'yellow');
return;
}
this.validateEnvironment(env);
break;
case 'generate':
if (!env) {
colorLog('❌ Environment name required', 'red');
colorLog('Usage: npm run env:generate <environment>', 'yellow');
return;
}
this.generateEnvFile(env);
break;
case 'list':
this.listEnvironments();
break;
case 'compare':
const env1 = args[1];
const env2 = args[2];
if (!env1 || !env2) {
colorLog('❌ Two environment names required', 'red');
colorLog('Usage: npm run env:compare <env1> <env2>', 'yellow');
return;
}
this.compareEnvironments(env1, env2);
break;
default:
colorLog('❌ Unknown command', 'red');
colorLog('Available commands:', 'cyan');
colorLog(' validate <env> - Validate environment configuration', 'cyan');
colorLog(' generate <env> - Generate environment file', 'cyan');
colorLog(' list - List all environments', 'cyan');
colorLog(' compare <env1> <env2> - Compare two environments', 'cyan');
break;
}
}
}
if (require.main === module) {
const manager = new EnvironmentScriptManager();
manager.run();
}
module.exports = EnvironmentScriptManager;
9. Create Environment Switching Script
Create scripts/switch-environment.js:
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// ANSI color codes
const colors = {
reset: '\x1b[0m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36c',
magenta: '\x1b[35m',
};
function colorLog(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
class EnvironmentSwitcher {
constructor() {
this.envDir = path.join(process.cwd(), 'environments');
this.rootEnvFile = path.join(process.cwd(), '.env.local');
}
switchToEnvironment(env) {
const envFile = path.join(this.envDir, `.env.${env}`);
if (!fs.existsSync(envFile)) {
colorLog(`❌ Environment file not found: ${envFile}`, 'red');
return false;
}
try {
// Read environment file
const envContent = fs.readFileSync(envFile, 'utf8');
// Backup current .env.local if it exists
if (fs.existsSync(this.rootEnvFile)) {
const backupFile = path.join(process.cwd(), '.env.local.backup');
fs.writeFileSync(backupFile, fs.readFileSync(this.rootEnvFile));
colorLog('📋 Backed up current .env.local to .env.local.backup', 'yellow');
}
// Write new environment file
fs.writeFileSync(this.rootEnvFile, envContent);
colorLog(`✅ Switched to environment: ${env}`, 'green');
colorLog(`📄 Environment file: ${this.rootEnvFile}`, 'cyan');
return true;
} catch (error) {
colorLog(`❌ Failed to switch environment: ${env}`, 'red');
return false;
}
}
getCurrentEnvironment() {
if (!fs.existsSync(this.rootEnvFile)) {
colorLog('❌ No .env.local file found', 'red');
return null;
}
try {
const envContent = fs.readFileSync(this.rootEnvFile, 'utf8');
const lines = envContent.split('\n');
for (const line of lines) {
if (line.startsWith('NEXT_PUBLIC_ENVIRONMENT=')) {
const env = line.split('=')[1];
colorLog(`📍 Current environment: ${env}`, 'blue');
return env;
}
}
colorLog('⚠️ Environment not specified in .env.local', 'yellow');
return null;
} catch (error) {
colorLog('❌ Failed to read current environment', 'red');
return null;
}
}
listAvailableEnvironments() {
if (!fs.existsSync(this.envDir)) {
colorLog('❌ Environments directory not found', 'red');
return;
}
const envFiles = fs.readdirSync(this.envDir).filter(file => file.startsWith('.env.'));
const environments = envFiles.map(file => file.replace('.env.', '').replace('.local', ''));
colorLog('📋 Available environments:', 'magenta');
environments.forEach(env => {
colorLog(` • ${env}`, 'cyan');
});
}
run() {
const args = process.argv.slice(2);
const command = args[0] || 'current';
const env = args[1];
switch (command) {
case 'switch':
case 'set':
if (!env) {
colorLog('❌ Environment name required', 'red');
colorLog('Usage: npm run env:switch <environment>', 'yellow');
return;
}
this.switchToEnvironment(env);
break;
case 'current':
this.getCurrentEnvironment();
break;
case 'list':
this.listAvailableEnvironments();
break;
default:
colorLog('❌ Unknown command', 'red');
colorLog('Available commands:', 'cyan');
colorLog(' switch <env> - Switch to environment', 'cyan');
colorLog(' current - Show current environment', 'cyan');
colorLog(' list - List available environments', 'cyan');
break;
}
}
}
if (require.main === module) {
const switcher = new EnvironmentSwitcher();
switcher.run();
}
module.exports = EnvironmentSwitcher;
10. Update Package.json Scripts
Update package.json scripts:
{
"scripts": {
"env:validate": "node scripts/environment-manager.js validate",
"env:generate": "node scripts/environment-manager.js generate",
"env:list": "node scripts/environment-manager.js list",
"env:compare": "node scripts/environment-manager.js compare",
"env:switch": "node scripts/switch-environment.js switch",
"env:current": "node scripts/switch-environment.js current",
"env:setup": "npm run env:generate development && npm run env:generate staging && npm run env:generate production",
"env:dev": "npm run env:switch development",
"env:staging": "npm run env:switch staging",
"env:prod": "npm run env:switch production"
}
}
Code Examples
Environment Management Commands
# Setup all environment files
npm run env:setup
# Validate environment configuration
npm run env:validate production
# Generate environment file
npm run env:generate production
# List all environments
npm run env:list
# Compare environments
npm run env:compare development production
# Switch environment
npm run env:switch staging
# Check current environment
npm run env:current
# Quick switches
npm run env:dev
npm run env:staging
npm run env:prod
Using Environment Config in Code
// Server-side usage
import { getEnvironmentConfig, isProduction } from '@/lib/environment';
export function getDatabaseUrl() {
const config = getEnvironmentConfig();
return config.database.url;
}
export function shouldEnableAnalytics() {
return isProduction() || getEnvironmentConfig().features.analytics;
}
// Client-side usage
'use client';
import { useEnvironment } from '@/lib/environment';
export function EnvironmentIndicator() {
const { environment, isDevelopment, isProduction } = useEnvironment();
if (isProduction) return null;
return (
<div className="fixed top-4 right-4 bg-yellow-100 text-yellow-800 px-3 py-1 rounded text-sm">
{environment.toUpperCase()}
</div>
);
}
Environment-Specific API Configuration
// src/lib/api.ts
import { getEnvironmentConfig } from '@/lib/environment';
export const apiConfig = {
baseURL: getEnvironmentConfig().apiUrl,
timeout: isDevelopment() ? 10000 : 5000,
retries: isProduction() ? 3 : 1,
};
export function createApiClient() {
const config = getEnvironmentConfig();
return {
baseURL: config.apiUrl,
headers: {
'Content-Type': 'application/json',
'X-Environment': config.name,
},
};
}
Configuration Templates
Complete Environment Structure
environments/
├── development/
│ └── .env.development
├── staging/
│ └── .env.staging
└── production/
└── .env.production
config/
└── environments/
├── schema.json
├── development.json
├── staging.json
└── production.json
scripts/
├── environment-manager.js
└── switch-environment.js
Best Practices
- Use separate configs - Environment-specific configurations
- Validate configurations - Schema validation for consistency
- Never commit secrets - Use environment variables
- Document environments - Clear descriptions and purposes
- Use feature flags - Environment-specific feature toggles
- Implement switching - Easy environment switching
- Monitor environments - Track performance and errors
- Test environments - Validate configurations work
Stop Conditions
STOP and report if:
- Environment configuration errors
- Schema validation failures
- File permission issues
- Configuration conflicts
Expected Outcomes:
- All environments configured
- Environment switching working
- Validation scripts functional
- Configuration schema working
- Environment utilities available
Verification Checklist
- Environment structure created
- Configuration schemas defined
- All environment configs created
- Environment manager working
- Environment utilities functional
- Management scripts working
- Switching mechanism functional
- Package.json scripts updated
- Validation working correctly
- Documentation complete
Version: 1.0.0 Last Updated: 2026-01-31 Skill Category: Architecture - Deployment
