๐Ÿ“… let's chat! explore the endless possibilities creating industries that don't exist. click here

speak-multi-env-setup

Configure Speak across development, staging, and production environments. Use when setting up multi-environment deployments, configuring per-environment secrets, or implementing environment-specific Speak configurations. Trigger with phrases like "speak environments", "speak staging", "speak dev prod", "speak environment setup", "speak config by env". allowed-tools: Read, Write, Edit, Bash(aws:*), Bash(gcloud:*), Bash(vault:*) version: 1.0.0 license: MIT author: Jeremy Longshore <jeremy@intentsolutions.io>

Allowed Tools

No tools specified

Provided by Plugin

speak-pack

Claude Code skill pack for Speak AI Language Learning Platform (24 skills)

saas packs v1.0.0
View Plugin

Installation

This skill is included in the speak-pack plugin:

/plugin install speak-pack@claude-code-plugins-plus

Click to copy

Instructions

# Speak Multi-Environment Setup ## Overview Configure Speak across development, staging, and production environments for language learning applications. ## Prerequisites - Separate Speak accounts or API keys per environment - Secret management solution (Vault, AWS Secrets Manager, etc.) - CI/CD pipeline with environment variables - Environment detection in application ## Environment Strategy | Environment | Purpose | API Keys | Data | Languages | |-------------|---------|----------|------|-----------| | Development | Local dev | Sandbox keys | Mock/test | All enabled | | Staging | Pre-prod validation | Staging keys | Test data | All enabled | | Production | Live users | Production keys | Real data | Enabled per plan | ## Configuration Structure ``` config/ โ”œโ”€โ”€ speak/ โ”‚ โ”œโ”€โ”€ base.json # Shared config โ”‚ โ”œโ”€โ”€ development.json # Dev overrides โ”‚ โ”œโ”€โ”€ staging.json # Staging overrides โ”‚ โ””โ”€โ”€ production.json # Prod overrides ``` ### base.json ```json { "timeout": 30000, "retries": 3, "cache": { "enabled": true, "ttlSeconds": 300 }, "audio": { "maxDuration": 60, "format": "wav", "sampleRate": 16000 }, "supportedLanguages": ["en", "es", "fr", "de", "ko", "ja", "zh-CN", "pt-BR"] } ``` ### development.json ```json { "baseUrl": "https://api-sandbox.speak.com", "debug": true, "cache": { "enabled": false }, "mockMode": true, "features": { "experimentalTutor": true, "betaSpeechEngine": true, "allLanguages": true } } ``` ### staging.json ```json { "baseUrl": "https://api-staging.speak.com", "debug": false, "features": { "experimentalTutor": true, "betaSpeechEngine": false, "allLanguages": true }, "rateLimits": { "lessonsPerHour": 100, "audioMinutesPerHour": 60 } } ``` ### production.json ```json { "baseUrl": "https://api.speak.com", "debug": false, "retries": 5, "features": { "experimentalTutor": false, "betaSpeechEngine": false, "allLanguages": false }, "rateLimits": { "lessonsPerHour": 1000, "audioMinutesPerHour": 500 } } ``` ## Environment Detection ```typescript // src/speak/config.ts import baseConfig from '../../config/speak/base.json'; type Environment = 'development' | 'staging' | 'production'; function detectEnvironment(): Environment { // Check multiple sources for environment const env = process.env.SPEAK_ENV || process.env.NODE_ENV || 'development'; const validEnvs: Environment[] = ['development', 'staging', 'production']; return validEnvs.includes(env as Environment) ? (env as Environment) : 'development'; } export function getSpeakConfig(): SpeakConfig { const env = detectEnvironment(); const envConfig = require(`../../config/speak/${env}.json`); return { ...baseConfig, ...envConfig, apiKey: process.env.SPEAK_API_KEY!, appId: process.env.SPEAK_APP_ID!, webhookSecret: process.env.SPEAK_WEBHOOK_SECRET, environment: env, }; } ``` ## Secret Management by Environment ### Local Development ```bash # .env.local (git-ignored) SPEAK_ENV=development SPEAK_API_KEY=sk_sandbox_*** SPEAK_APP_ID=app_dev_*** SPEAK_MOCK_MODE=true ``` ### CI/CD (GitHub Actions) ```yaml jobs: deploy: environment: ${{ matrix.environment }} env: SPEAK_ENV: ${{ matrix.environment }} SPEAK_API_KEY: ${{ secrets[format('SPEAK_API_KEY_{0}', matrix.environment)] }} SPEAK_APP_ID: ${{ secrets[format('SPEAK_APP_ID_{0}', matrix.environment)] }} strategy: matrix: environment: [staging, production] ``` ### Production (Vault/Secrets Manager) ```bash # AWS Secrets Manager aws secretsmanager get-secret-value \ --secret-id speak/production/credentials # GCP Secret Manager gcloud secrets versions access latest \ --secret=speak-production-api-key # HashiCorp Vault vault kv get -field=api_key secret/speak/production ``` ## Environment Isolation ### Prevent Production Operations in Non-Prod ```typescript function guardProductionOperation(operation: string): void { const config = getSpeakConfig(); if (config.environment !== 'production') { console.warn(`[speak] ${operation} blocked in ${config.environment}`); throw new Error(`${operation} only allowed in production`); } } // Usage async function deleteUserData(userId: string): Promise { guardProductionOperation('deleteUserData'); await speakClient.users.delete(userId); } ``` ### Environment-Specific Lesson Restrictions ```typescript function getAvailableLanguages(): string[] { const config = getSpeakConfig(); if (config.features?.allLanguages) { return config.supportedLanguages; } // Production: Only enabled languages for user's plan return getUserPlanLanguages(); } function canAccessFeature(feature: string): boolean { const config = getSpeakConfig(); return config.features?.[feature] ?? false; } ``` ## Feature Flags by Environment ```typescript interface FeatureFlags { experimentalTutor: boolean; betaSpeechEngine: boolean; newPronunciationModel: boolean; gamificationV2: boolean; offlineMode: boolean; } const featureFlags: Record = { development: { experimentalTutor: true, betaSpeechEngine: true, newPronunciationModel: true, gamificationV2: true, offlineMode: true, }, staging: { experimentalTutor: true, betaSpeechEngine: true, newPronunciationModel: true, gamificationV2: false, offlineMode: false, }, production: { experimentalTutor: false, betaSpeechEngine: false, newPronunciationModel: false, gamificationV2: false, offlineMode: false, }, }; export function isFeatureEnabled(feature: keyof FeatureFlags): boolean { const env = detectEnvironment(); return featureFlags[env][feature]; } ``` ## Environment-Specific Audio Storage ```typescript interface AudioStorageConfig { type: 'local' | 's3' | 'gcs'; bucket?: string; encryption: boolean; retention: number; // days } const audioStorage: Record = { development: { type: 'local', encryption: false, retention: 1, }, staging: { type: 's3', bucket: 'speak-staging-audio', encryption: true, retention: 7, }, production: { type: 's3', bucket: 'speak-production-audio', encryption: true, retention: 30, }, }; ``` ## Environment Health Checks ```typescript async function verifyEnvironmentConfig(): Promise { const config = getSpeakConfig(); const checks = { apiKeyValid: false, canConnect: false, correctEnvironment: false, featuresAccessible: false, }; try { // Verify API key const health = await speakClient.health.check(); checks.apiKeyValid = true; checks.canConnect = health.healthy; // Verify we're hitting the right environment const expectedBase = config.baseUrl; checks.correctEnvironment = health.endpoint.includes( config.environment === 'production' ? 'api.speak.com' : `api-${config.environment}` ); // Verify feature access if (config.features?.experimentalTutor) { checks.featuresAccessible = await canAccessExperimentalTutor(); } else { checks.featuresAccessible = true; } } catch (error) { console.error('Environment verification failed:', error); } return { environment: config.environment, checks, allPassed: Object.values(checks).every(Boolean), }; } ``` ## Output - Multi-environment config structure - Environment detection logic - Secure secret management - Production safeguards enabled - Feature flags by environment ## Error Handling | Issue | Cause | Solution | |-------|-------|----------| | Wrong environment | Missing SPEAK_ENV | Set environment variable | | Secret not found | Wrong secret path | Verify secret manager config | | Config merge fails | Invalid JSON | Validate config files | | Production guard triggered | Wrong environment | Check SPEAK_ENV value | | Feature unavailable | Wrong environment | Verify feature flags | ## Examples ### Quick Environment Check ```typescript const config = getSpeakConfig(); console.log(`Environment: ${config.environment}`); console.log(`API Base: ${config.baseUrl}`); console.log(`Mock Mode: ${config.mockMode ? 'ON' : 'OFF'}`); console.log(`Features:`, config.features); ``` ### Environment Switching Script ```bash #!/bin/bash # switch-speak-env.sh case "$1" in dev) export SPEAK_ENV=development export SPEAK_API_KEY=$(vault kv get -field=api_key secret/speak/development) ;; staging) export SPEAK_ENV=staging export SPEAK_API_KEY=$(vault kv get -field=api_key secret/speak/staging) ;; prod) export SPEAK_ENV=production export SPEAK_API_KEY=$(vault kv get -field=api_key secret/speak/production) ;; esac echo "Switched to $SPEAK_ENV environment" ``` ## Resources - [Speak Environments Guide](https://developer.speak.com/docs/environments) - [12-Factor App Config](https://12factor.net/config) - [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/) ## Next Steps For observability setup, see `speak-observability`.

Skill file: plugins/saas-packs/speak-pack/skills/speak-multi-env-setup/SKILL.md