CtrlK
BlogDocsLog inGet started
Tessl Logo

deepgram-multi-env-setup

Configure Deepgram multi-environment setup for dev, staging, and production. Use when setting up environment-specific configurations, managing multiple Deepgram projects, or implementing environment isolation. Trigger: "deepgram environments", "deepgram staging", "deepgram dev prod", "multi-environment deepgram", "deepgram config management".

79

Quality

76%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

Optimize this skill with Tessl

npx tessl skill review --optimize ./plugins/saas-packs/deepgram-pack/skills/deepgram-multi-env-setup/SKILL.md
SKILL.md
Quality
Evals
Security

Deepgram Multi-Environment Setup

Overview

Configure isolated Deepgram environments for development, staging, and production. Each environment uses a separate Deepgram project, scoped API keys, environment-specific model selection, and validated configuration. Includes typed config, client factory, Docker Compose profiles, and Kubernetes overlays.

Environment Strategy

SettingDevelopmentStagingProduction
Modelbase (fast, cheap)nova-3nova-3
Concurrency520100
DiarizationOffOnOn
PII RedactionOffOnOn
Callback URLlocalhost:3000staging.example.comapi.example.com
Key RotationManualMonthly90-day auto

Instructions

Step 1: Typed Environment Configuration

interface DeepgramEnvConfig {
  apiKey: string;
  projectId: string;
  model: 'base' | 'nova-2' | 'nova-3';
  maxConcurrency: number;
  features: {
    diarize: boolean;
    smart_format: boolean;
    redact: string[] | false;
    summarize: boolean;
  };
  callbackBaseUrl?: string;
  timeout: number;
}

function loadConfig(env: string): DeepgramEnvConfig {
  const configs: Record<string, DeepgramEnvConfig> = {
    development: {
      apiKey: process.env.DEEPGRAM_API_KEY_DEV!,
      projectId: process.env.DEEPGRAM_PROJECT_ID_DEV!,
      model: 'base',
      maxConcurrency: 5,
      features: {
        diarize: false,
        smart_format: true,
        redact: false,
        summarize: false,
      },
      callbackBaseUrl: 'http://localhost:3000',
      timeout: 60000,
    },
    staging: {
      apiKey: process.env.DEEPGRAM_API_KEY_STAGING!,
      projectId: process.env.DEEPGRAM_PROJECT_ID_STAGING!,
      model: 'nova-3',
      maxConcurrency: 20,
      features: {
        diarize: true,
        smart_format: true,
        redact: ['pci', 'ssn'],
        summarize: true,
      },
      callbackBaseUrl: 'https://staging.example.com',
      timeout: 30000,
    },
    production: {
      apiKey: process.env.DEEPGRAM_API_KEY_PRODUCTION!,
      projectId: process.env.DEEPGRAM_PROJECT_ID_PRODUCTION!,
      model: 'nova-3',
      maxConcurrency: 100,
      features: {
        diarize: true,
        smart_format: true,
        redact: ['pci', 'ssn'],
        summarize: true,
      },
      callbackBaseUrl: 'https://api.example.com',
      timeout: 30000,
    },
  };

  const config = configs[env];
  if (!config) throw new Error(`Unknown environment: ${env}. Use: development, staging, production`);
  if (!config.apiKey) throw new Error(`DEEPGRAM_API_KEY_${env.toUpperCase()} not set`);
  return config;
}

const env = process.env.NODE_ENV ?? 'development';
const config = loadConfig(env);

Step 2: Client Factory

import { createClient, DeepgramClient } from '@deepgram/sdk';

class DeepgramClientFactory {
  private static clients = new Map<string, DeepgramClient>();

  static getClient(env?: string): DeepgramClient {
    const environment = env ?? process.env.NODE_ENV ?? 'development';

    if (!this.clients.has(environment)) {
      const config = loadConfig(environment);
      this.clients.set(environment, createClient(config.apiKey));
      console.log(`Deepgram client created for: ${environment} (model: ${config.model})`);
    }

    return this.clients.get(environment)!;
  }

  // Convenience: transcribe with environment defaults
  static async transcribe(url: string, overrides: Record<string, any> = {}) {
    const environment = process.env.NODE_ENV ?? 'development';
    const config = loadConfig(environment);
    const client = this.getClient(environment);

    const { result, error } = await client.listen.prerecorded.transcribeUrl(
      { url },
      {
        model: config.model,
        smart_format: config.features.smart_format,
        diarize: config.features.diarize,
        redact: config.features.redact || undefined,
        summarize: config.features.summarize ? 'v2' : undefined,
        ...overrides,
      }
    );
    if (error) throw error;
    return result;
  }

  // Reset for key rotation
  static reset(env?: string) {
    if (env) {
      this.clients.delete(env);
    } else {
      this.clients.clear();
    }
  }
}

Step 3: Environment Variables Template

# .env.development
DEEPGRAM_API_KEY_DEV=dev-key-here
DEEPGRAM_PROJECT_ID_DEV=dev-project-id

# .env.staging
DEEPGRAM_API_KEY_STAGING=staging-key-here
DEEPGRAM_PROJECT_ID_STAGING=staging-project-id

# .env.production (use secret manager, not file)
# DEEPGRAM_API_KEY_PRODUCTION=production-key-here
# DEEPGRAM_PROJECT_ID_PRODUCTION=production-project-id

Step 4: Docker Compose Multi-Profile

# docker-compose.yml
x-common: &common
  build: .
  restart: unless-stopped
  healthcheck:
    test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"]
    interval: 30s
    timeout: 10s

services:
  app-dev:
    <<: *common
    profiles: ["development"]
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - DEEPGRAM_API_KEY_DEV=${DEEPGRAM_API_KEY_DEV}
      - DEEPGRAM_PROJECT_ID_DEV=${DEEPGRAM_PROJECT_ID_DEV}

  app-staging:
    <<: *common
    profiles: ["staging"]
    ports:
      - "3001:3000"
    environment:
      - NODE_ENV=staging
      - DEEPGRAM_API_KEY_STAGING=${DEEPGRAM_API_KEY_STAGING}
      - DEEPGRAM_PROJECT_ID_STAGING=${DEEPGRAM_PROJECT_ID_STAGING}

  app-production:
    <<: *common
    profiles: ["production"]
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DEEPGRAM_API_KEY_PRODUCTION=${DEEPGRAM_API_KEY_PRODUCTION}
      - DEEPGRAM_PROJECT_ID_PRODUCTION=${DEEPGRAM_PROJECT_ID_PRODUCTION}
    deploy:
      resources:
        limits:
          memory: 512M
# Usage:
docker compose --profile development up
docker compose --profile staging up
docker compose --profile production up

Step 5: Kubernetes Kustomize Overlays

# k8s/base/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: deepgram-config
data:
  DEEPGRAM_MODEL: "nova-3"
  DEEPGRAM_SMART_FORMAT: "true"

---
# k8s/overlays/development/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
  - ../../base
patchesStrategicMerge:
  - configmap-patch.yaml
secretGenerator:
  - name: deepgram-secrets
    literals:
      - api-key=dev-key-here

---
# k8s/overlays/development/configmap-patch.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: deepgram-config
data:
  DEEPGRAM_MODEL: "base"
  DEEPGRAM_MAX_CONCURRENCY: "5"

Step 6: Environment Validation

async function validateEnvironments() {
  const envs = ['development', 'staging', 'production'];
  const results: Record<string, { valid: boolean; error?: string }> = {};

  for (const env of envs) {
    try {
      const config = loadConfig(env);
      const client = createClient(config.apiKey);

      // Test 1: Key validity
      const { error: authError } = await client.manage.getProjects();
      if (authError) throw new Error(`Auth failed: ${authError.message}`);

      // Test 2: Project access
      const { error: projError } = await client.manage.getProject(config.projectId);
      if (projError) throw new Error(`Project access failed: ${projError.message}`);

      // Test 3: Transcription works
      const { error: sttError } = await client.listen.prerecorded.transcribeUrl(
        { url: 'https://static.deepgram.com/examples/Bueller-Life-moves-702702706.wav' },
        { model: config.model, smart_format: true }
      );
      if (sttError) throw new Error(`STT failed: ${sttError.message}`);

      results[env] = { valid: true };
      console.log(`[PASS] ${env}`);
    } catch (err: any) {
      results[env] = { valid: false, error: err.message };
      console.log(`[FAIL] ${env}: ${err.message}`);
    }
  }

  const allValid = Object.values(results).every(r => r.valid);
  console.log(`\nValidation: ${allValid ? 'ALL PASS' : 'FAILURES DETECTED'}`);
  return results;
}

Output

  • Typed environment configuration (dev/staging/prod)
  • Singleton client factory per environment
  • Docker Compose multi-profile setup
  • Kubernetes Kustomize overlays
  • Environment validation script

Error Handling

IssueCauseSolution
DEEPGRAM_API_KEY_DEV not setMissing env varSet in .env.development
Wrong model in stagingConfig mismatchCheck loadConfig mapping
Cross-env key usedShared keyCreate separate projects per environment
Validation fails for one envKey expiredRotate key for that environment

Resources

  • Deepgram Projects
  • API Key Management
  • Kustomize
Repository
jeremylongshore/claude-code-plugins-plus-skills
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.