# Speak Deploy Integration

> Deploy Speak language learning integrations to Vercel, Fly.io, and Cloud Run platforms. Use when deploying Speak-powered applications to production, configuring platform-specific secrets, or setting up deployment pipelines. Trigger with phrases like "deploy speak", "speak Vercel", "speak production deploy", "speak Cloud Run", "speak Fly.io".

- Skill: `tools-only/speak-deploy-integration` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds add tools-only/speak-deploy-integration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/speak-deploy-integration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: MIT
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/tools-only/speak-deploy-integration

---


# Speak Deploy Integration

## Overview
Deploy Speak-powered language learning applications to popular platforms with proper secrets management.

## Prerequisites
- Speak API keys for production environment
- Platform CLI installed (vercel, fly, or gcloud)
- Application code ready for deployment
- Environment variables documented
- Audio storage configured

## Vercel Deployment

### Environment Setup
```bash
# Add Speak secrets to Vercel
vercel secrets add speak_api_key sk_live_***
vercel secrets add speak_app_id app_***
vercel secrets add speak_webhook_secret whsec_***

# Link to project
vercel link

# Deploy preview
vercel

# Deploy production
vercel --prod
```

### vercel.json Configuration
```json
{
  "env": {
    "SPEAK_API_KEY": "@speak_api_key",
    "SPEAK_APP_ID": "@speak_app_id"
  },
  "functions": {
    "api/**/*.ts": {
      "maxDuration": 60
    },
    "api/speech/**/*.ts": {
      "maxDuration": 120,
      "memory": 1024
    }
  },
  "headers": [
    {
      "source": "/api/speech/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Origin", "value": "*" },
        { "key": "Access-Control-Allow-Methods", "value": "POST, OPTIONS" }
      ]
    }
  ]
}
```

### Next.js API Routes for Speak
```typescript
// pages/api/speak/session.ts
import { SpeakClient } from '@speak/language-sdk';
import type { NextApiRequest, NextApiResponse } from 'next';

const client = new SpeakClient({
  apiKey: process.env.SPEAK_API_KEY!,
  appId: process.env.SPEAK_APP_ID!,
});

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { language, topic, difficulty } = req.body;

    const session = await client.tutor.startSession({
      language,
      topic,
      difficulty,
    });

    res.json({ sessionId: session.id });
  } catch (error) {
    console.error('Speak session error:', error);
    res.status(500).json({ error: 'Failed to start session' });
  }
}
```

## Fly.io Deployment

### fly.toml
```toml
app = "my-speak-app"
primary_region = "iad"

[env]
  NODE_ENV = "production"
  SPEAK_TARGET_LANGUAGE = "es"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = false  # Keep warm for low latency
  auto_start_machines = true
  min_machines_running = 1

[[services.http_checks]]
  interval = 10000
  grace_period = "10s"
  method = "get"
  path = "/health"
  protocol = "http"
  timeout = 2000

# Larger instance for audio processing
[[vm]]
  cpu_kind = "performance"
  cpus = 2
  memory_mb = 2048
```

### Secrets Configuration
```bash
# Set Speak secrets
fly secrets set SPEAK_API_KEY=sk_live_***
fly secrets set SPEAK_APP_ID=app_***
fly secrets set SPEAK_WEBHOOK_SECRET=whsec_***

# Set audio storage (if using external)
fly secrets set AUDIO_STORAGE_URL=https://storage.example.com
fly secrets set AUDIO_ENCRYPTION_KEY=base64_key_here

# Deploy
fly deploy
```

### Volume for Audio Caching
```bash
# Create volume for audio cache
fly volumes create speak_cache --size 10 --region iad

# Update fly.toml
[mounts]
  source = "speak_cache"
  destination = "/app/cache"
```

## Google Cloud Run

### Dockerfile
```dockerfile
FROM node:20-slim

WORKDIR /app

# Install audio dependencies for speech processing
RUN apt-get update && apt-get install -y \
    ffmpeg \
    libsox-fmt-all \
    && rm -rf /var/lib/apt/lists/*

COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

# Non-root user for security
USER node

CMD ["npm", "start"]
```

### Deploy Script
```bash
#!/bin/bash
# deploy-cloud-run.sh

PROJECT_ID="${GOOGLE_CLOUD_PROJECT}"
SERVICE_NAME="speak-service"
REGION="us-central1"

# Build and push image
gcloud builds submit --tag gcr.io/$PROJECT_ID/$SERVICE_NAME

# Deploy to Cloud Run
gcloud run deploy $SERVICE_NAME \
  --image gcr.io/$PROJECT_ID/$SERVICE_NAME \
  --region $REGION \
  --platform managed \
  --allow-unauthenticated \
  --memory 2Gi \
  --cpu 2 \
  --timeout 120 \
  --concurrency 80 \
  --min-instances 1 \
  --set-secrets=SPEAK_API_KEY=speak-api-key:latest,SPEAK_APP_ID=speak-app-id:latest

# Set up Cloud Storage for audio (optional)
gsutil mb -l $REGION gs://$PROJECT_ID-speak-audio
gcloud run services update $SERVICE_NAME \
  --set-env-vars=AUDIO_BUCKET=gs://$PROJECT_ID-speak-audio
```

### Cloud Run with WebSocket Support
```yaml
# cloudrun.yaml (for WebSocket connections needed for real-time speech)
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: speak-service
spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/execution-environment: gen2
        run.googleapis.com/session-affinity: "true"
    spec:
      containerConcurrency: 80
      timeoutSeconds: 300
      containers:
        - image: gcr.io/PROJECT_ID/speak-service
          ports:
            - name: http1
              containerPort: 3000
          resources:
            limits:
              cpu: "2"
              memory: 2Gi
```

## Environment Configuration Pattern

```typescript
// config/speak.ts
interface SpeakConfig {
  apiKey: string;
  appId: string;
  environment: 'development' | 'staging' | 'production';
  webhookSecret?: string;
  audioStorage?: {
    type: 'local' | 's3' | 'gcs';
    bucket?: string;
  };
}

export function getSpeakConfig(): SpeakConfig {
  const env = process.env.NODE_ENV || 'development';

  return {
    apiKey: process.env.SPEAK_API_KEY!,
    appId: process.env.SPEAK_APP_ID!,
    environment: env as SpeakConfig['environment'],
    webhookSecret: process.env.SPEAK_WEBHOOK_SECRET,
    audioStorage: {
      type: process.env.AUDIO_STORAGE_TYPE as any || 'local',
      bucket: process.env.AUDIO_BUCKET,
    },
  };
}
```

## Health Check Endpoint

```typescript
// api/health.ts
import { SpeakClient } from '@speak/language-sdk';

const client = new SpeakClient({
  apiKey: process.env.SPEAK_API_KEY!,
  appId: process.env.SPEAK_APP_ID!,
});

export async function GET() {
  const start = Date.now();

  try {
    const speakHealth = await client.health.check();

    return Response.json({
      status: speakHealth.healthy ? 'healthy' : 'degraded',
      services: {
        speak: {
          connected: speakHealth.healthy,
          latencyMs: Date.now() - start,
        },
      },
      timestamp: new Date().toISOString(),
    });
  } catch (error) {
    return Response.json({
      status: 'unhealthy',
      services: {
        speak: {
          connected: false,
          error: error instanceof Error ? error.message : 'Unknown error',
        },
      },
      timestamp: new Date().toISOString(),
    }, { status: 503 });
  }
}
```

## Output
- Application deployed to production
- Speak secrets securely configured
- Health check endpoint functional
- Audio processing infrastructure ready
- Environment-specific configuration in place

## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Secret not found | Missing configuration | Add secret via platform CLI |
| Deploy timeout | Large build or audio deps | Increase build timeout |
| Health check fails | Wrong API key | Verify environment variable |
| Cold start issues | No warm-up | Configure minimum instances |
| Audio timeout | Processing too slow | Increase memory/CPU |

## Examples

### Quick Deploy Script
```bash
#!/bin/bash
# Platform-agnostic deploy helper
case "$1" in
  vercel)
    vercel secrets add speak_api_key "$SPEAK_API_KEY"
    vercel secrets add speak_app_id "$SPEAK_APP_ID"
    vercel --prod
    ;;
  fly)
    fly secrets set SPEAK_API_KEY="$SPEAK_API_KEY"
    fly secrets set SPEAK_APP_ID="$SPEAK_APP_ID"
    fly deploy
    ;;
  cloudrun)
    gcloud run deploy speak-service \
      --set-secrets=SPEAK_API_KEY=speak-api-key:latest
    ;;
esac
```

## Resources
- [Vercel Documentation](https://vercel.com/docs)
- [Fly.io Documentation](https://fly.io/docs)
- [Cloud Run Documentation](https://cloud.google.com/run/docs)
- [Speak Deploy Guide](https://developer.speak.com/docs/deploy)

## Next Steps
For webhook handling, see `speak-webhooks-events`.

