Skip to content
Environment Management logo

Environment Management

> **Skill Purpose:** Multi-environment configuration and deployment patterns

Coverage-Creatives/zeus0installs0stars

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:

  1. Define environment hierarchy (dev/​staging/​prod)
  2. Create environment-specific configurations
  3. Establish configuration validation
  4. Set up deployment environment mapping
  5. 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

  1. Use separate configs - Environment-specific configurations
  2. Validate configurations - Schema validation for consistency
  3. Never commit secrets - Use environment variables
  4. Document environments - Clear descriptions and purposes
  5. Use feature flags - Environment-specific feature toggles
  6. Implement switching - Easy environment switching
  7. Monitor environments - Track performance and errors
  8. 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