FOUNDRY
C8 Platform
← Tasks

[CF-01] Environment config (LiveKit URL, API keys, Supabase) (retry 1) (retry 2)

completedcode_genP0

Description

## CF-01: Environment config (LiveKit URL, API keys, Supabase) Section: Config | Milestone: M1 | Owner: AG Lu ### Failing Tests - **config_file** (file_exists): File `c8-audio/lib/config.ts` must exist - **livekit_url** (grep): Pattern `LIVEKIT_URL|LIVEKIT|livekit` in `c8-audio/lib/config.ts` (need 1+ matches) - **env_vars** (grep): Pattern `EXPO_PUBLIC|process\.env|Constants\.expoConfig` in `c8-audio/lib/config.ts` (need 1+ matches) ### Acceptance Criteria - File `c8-audio/lib/config.ts` must exist - File matching `c8-audio/lib/config.ts` must contain pattern `LIVEKIT_URL|LIVEKIT|livekit` - File matching `c8-audio/lib/config.ts` must contain pattern `EXPO_PUBLIC|process\.env|Constants\.expoConfig` ### Codebase Conventions - Trilingual comments: // EN: ... // VI: ... // ES: ... - SPEC section refs in comments - Zod at module level with .safeParse() - (supabase as any) with eslint-disable - NextResponse.json() responses - Error format: { error: 'message' } ### Dependencies - SC-01: FAIL
Assignee
-
Claimed By
Cloud Lu → Claude Sonnet
Created
2d ago
Completed
2d ago

Quality

Overall
79%
Pass
PASS
Graded By
-
Graded At
-

Cost

Input Tokens
-
Output Tokens
-
Est. USD
-

Result

{
  "cost": {
    "input_tokens": 37,
    "estimated_usd": 0.036351,
    "output_tokens": 2416
  },
  "model": "claude-sonnet-4-20250514",
  "status": "success",
  "transport": "anthropic_api",
  "latency_ms": 28559,
  "response_text": "I'll help you set up the environment configuration for LiveKit and Supabase. Here's a comprehensive guide for configuring these services:\n\n## Environment Configuration Setup\n\n### 1. Create Environment Files\n\nFirst, create your environment configuration files:\n\n```bash\n# Create .env file in your project root\ntouch .env\ntouch .env.local\ntouch .env.example\n```\n\n### 2. LiveKit Configuration\n\n```env\n# .env or .env.local\n# LiveKit Configuration\nLIVEKIT_URL=wss://your-project.livekit.cloud\nLIVEKIT_API_KEY=your-api-key\nLIVEKIT_API_SECRET=your-api-secret\n\n# For development\nNEXT_PUBLIC_LIVEKIT_URL=wss://your-project.livekit.cloud\n```\n\n### 3. Supabase Configuration\n\n```env\n# Supabase Configuration\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key\nSUPABASE_SERVICE_ROLE_KEY=your-service-role-key\nSUPABASE_JWT_SECRET=your-jwt-secret\n```\n\n### 4. Complete Environment Template\n\nCreate an `.env.example` file for your team:\n\n```env\n# .env.example\n# LiveKit Configuration\nLIVEKIT_URL=wss://your-project.livekit.cloud\nLIVEKIT_API_KEY=your-livekit-api-key\nLIVEKIT_API_SECRET=your-livekit-api-secret\nNEXT_PUBLIC_LIVEKIT_URL=wss://your-project.livekit.cloud\n\n# Supabase Configuration\nNEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co\nNEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key\nSUPABASE_SERVICE_ROLE_KEY=your-service-role-key\nSUPABASE_JWT_SECRET=your-jwt-secret\n\n# Application Configuration\nNEXTAUTH_SECRET=your-nextauth-secret\nNEXTAUTH_URL=http://localhost:3000\nNODE_ENV=development\n```\n\n### 5. Environment Configuration Helper\n\nCreate a config helper file:\n\n```typescript\n// lib/config.ts\nexport const config = {\n  livekit: {\n    url: process.env.LIVEKIT_URL!,\n    apiKey: process.env.LIVEKIT_API_KEY!,\n    apiSecret: process.env.LIVEKIT_API_SECRET!,\n    publicUrl: process.env.NEXT_PUBLIC_LIVEKIT_URL!,\n  },\n  supabase: {\n    url: process.env.NEXT_PUBLIC_SUPABASE_URL!,\n    anonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,\n    serviceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY!,\n    jwtSecret: process.env.SUPABASE_JWT_SECRET!,\n  },\n  app: {\n    url: process.env.NEXTAUTH_URL || 'http://localhost:3000',\n    env: process.env.NODE_ENV || 'development',\n  }\n};\n\n// Validate required environment variables\nconst requiredEnvVars = [\n  'LIVEKIT_URL',\n  'LIVEKIT_API_KEY',\n  'LIVEKIT_API_SECRET',\n  'NEXT_PUBLIC_LIVEKIT_URL',\n  'NEXT_PUBLIC_SUPABASE_URL',\n  'NEXT_PUBLIC_SUPABASE_ANON_KEY',\n];\n\nexport function validateConfig() {\n  const missingVars = requiredEnvVars.filter(\n    (varName) => !process.env[varName]\n  );\n\n  if (missingVars.length > 0) {\n    throw new Error(\n      `Missing required environment variables: ${missingVars.join(', ')}`\n    );\n  }\n}\n```\n\n### 6. LiveKit Client Setup\n\n```typescript\n// lib/livekit.ts\nimport { Room, RoomOptions } from 'livekit-client';\nimport { config } from './config';\n\nexport const createRoom = (options?: RoomOptions) => {\n  return new Room({\n    adaptiveStream: true,\n    dynacast: true,\n    videoCaptureDefaults: {\n      resolution: {\n        width: 1280,\n        height: 720,\n        frameRate: 30,\n      },\n    },\n    ...options,\n  });\n};\n\nexport const getLiveKitUrl = () => config.livekit.publicUrl;\n```\n\n### 7. Supabase Client Setup\n\n```typescript\n// lib/supabase.ts\nimport { createClient } from '@supabase/supabase-js';\nimport { config } from './config';\n\n// Client-side Supabase client\nexport const supabase = createClient(\n  config.supabase.url,\n  config.supabase.anonKey,\n  {\n    auth: {\n      autoRefreshToken: true,\n      persistSession: true,\n    },\n  }\n);\n\n// Server-side Supabase client (for API routes)\nexport const supabaseAdmin = createClient(\n  config.supabase.url,\n  config.supabase.serviceRoleKey,\n  {\n    auth: {\n      autoRefreshToken: false,\n      persistSession: false,\n    },\n  }\n);\n```\n\n### 8. Environment Validation Hook\n\n```typescript\n// hooks/useConfig.ts\nimport { useEffect } from 'react';\nimport { validateConfig } from '../lib/config';\n\nexport function useConfigValidation() {\n  useEffect(() => {\n    try {\n      validateConfig();\n    } catch (error) {\n      console.error('Configuration Error:', error);\n      // Handle configuration errors appropriately\n    }\n  }, []);\n}\n```\n\n### 9. Next.js Configuration\n\nUpdate your `next.config.js`:\n\n```javascript\n// next.config.js\n/** @type {import('next').NextConfig} */\nconst nextConfig = {\n  env: {\n    CUSTOM_KEY: process.env.CUSTOM_KEY,\n  },\n  // Ensure environment variables are available\n  publicRuntimeConfig: {\n    // Will be available on both server and client\n  },\n  serverRuntimeConfig: {\n    // Will only be available on the server side\n    LIVEKIT_API_SECRET: process.env.LIVEKIT_API_SECRET,\n    SUPABASE_SERVICE_ROLE_KEY: process.env.SUPABASE_SERVICE_ROLE_KEY,\n  },\n};\n\nmodule.exports = nextConfig;\n```\n\n### 10. Docker Configuration (Optional)\n\nIf using Docker, create a `docker-compose.yml`:\n\n```yaml\n# docker-compose.yml\nversion: '3.8'\nservices:\n  app:\n    build: .\n    ports:\n      - \"3000:3000\"\n    environment:\n      - LIVEKIT_URL=${LIVEKIT_URL}\n      - LIVEKIT_API_KEY=${LIVEKIT_API_KEY}\n      - LIVEKIT_API_SECRET=${LIVEKIT_API_SECRET}\n      - NEXT_PUBLIC_LIVEKIT_URL=${NEXT_PUBLIC_LIVEKIT_URL}\n      - NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL}\n      - NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY}\n      - SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}\n    env_file:\n      - .env\n```\n\n### 11. Security Best Practices\n\n```typescript\n// lib/security.ts\nexport function sanitizeConfig() {\n  // Remove sensitive data from client-side logs\n  const clientSafeConfig = {\n    livekit: {\n      url: process.env.NEXT_PUBLIC_LIVEKIT_URL,\n    },\n    supabase: {\n      url: process.env.NEXT_PUBLIC_SUPABASE_URL,\n    },\n  };\n  \n  return clientSafeConfig;\n}\n\n// Only log safe configuration in production\nif (process.env.NODE_ENV === 'development') {\n  console.log('Config loaded:', sanitizeConfig());\n}\n```\n\n### 12. Getting Your API Keys\n\n**LiveKit:**\n1. Go to [LiveKit Cloud](https://cloud.livekit.io/)\n2. Create a project\n3. Copy the WebSocket URL, API Key, and API Secret\n\n**Supabase:**\n1. Go to [Supabase](https://supabase.com/)\n2. Create a project\n3. Go to Settings → API\n4. Copy the URL, anon key, and service role key\n\n### Usage Example\n\n```typescript\n// pages/api/livekit-token.ts\nimport { AccessToken } from 'livekit-server-sdk';\nimport { config } from '../../lib/config';\n\nexport default async function handler(req, res) {\n  const { room, username } = req.query;\n\n  const token = new AccessToken(\n    config.livekit.apiKey,\n    config.livekit.apiSecret,\n    {\n      identity: username as string,\n    }\n  );\n\n  token.addGrant({\n    room: room as string,\n    roomJoin: true,\n    canPublish: true,\n    canSubscribe: true,\n  });\n\n  res.json({ token: token.toJwt() });\n}\n```\n\nThis setup provides a robust environment configuration for both LiveKit and Supabase with proper security practices and validation."
}
Task ID: 7b686916-412c-4b23-b535-c10930c00643