| name | speak-local-dev-loop |
| description | Configure Speak local development with hot reload, testing, and mock tutors.
Use when setting up a development environment, configuring test workflows,
or establishing a fast iteration cycle with Speak language learning.
Trigger with phrases like "speak dev setup", "speak local development",
"speak dev environment", "develop with speak".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Speak Local Dev Loop
Overview
Set up a fast, reproducible local development workflow for Speak language learning integrations.
Prerequisites
- Completed
speak-install-auth setup
- Node.js 18+ with npm/pnpm
- Code editor with TypeScript support
- Git for version control
- Audio testing tools (optional)
Instructions
Step 1: Create Project Structure
my-speak-project/
├── src/
│ ├── speak/
│ │ ├── client.ts # Speak client wrapper
│ │ ├── config.ts # Configuration management
│ │ ├── tutor.ts # AI tutor service
│ │ ├── speech.ts # Speech recognition utilities
│ │ └── utils.ts # Helper functions
│ ├── lessons/
│ │ ├── vocabulary.ts # Vocabulary lesson logic
│ │ ├── conversation.ts # Conversation practice
│ │ └── pronunciation.ts # Pronunciation training
│ └── index.ts
├── tests/
│ ├── unit/
│ │ └── speak.test.ts
│ ├── integration/
│ │ └── lessons.test.ts
│ └── mocks/
│ └── speak-mock.ts # Mock tutor responses
├── .env.local # Local secrets (git-ignored)
├── .env.example # Template for team
├── .env.test # Test environment
└── package.json
Step 2: Configure Environment
cp .env.example .env.local
cat > .env.test << 'EOF'
SPEAK_API_KEY=test-key-for-mocks
SPEAK_APP_ID=test-app-id
SPEAK_MOCK_MODE=true
SPEAK_TARGET_LANGUAGE=es
EOF
npm install
npm run dev
Step 3: Setup Hot Reload
{
"scripts": {
"dev": "tsx watch src/index.ts",
"dev:lesson": "tsx watch src/lessons/conversation.ts",
"test": "vitest",
"test:watch": "vitest --watch",
"test:integration": "vitest run tests/integration"
}
}
Step 4: Configure Testing with Mocks
import { vi } from 'vitest';
export const mockTutorResponse = {
text: "Muy bien! Your pronunciation is improving.",
audioUrl: 'https://speak.com/mock-audio.mp3',
pronunciationScore: 85,
grammarCorrections: [],
suggestions: ['Try rolling your Rs more'],
};
export const mockSpeakClient = {
health: {
check: vi.fn().mockResolvedValue({ healthy: true }),
},
tutor: {
startSession: vi.fn().mockResolvedValue({
id: 'session-123',
status: 'active',
}),
getPrompt: vi.fn().mockResolvedValue({
text: 'Let\'s practice greetings in Spanish!',
audioUrl: 'https://speak.com/mock-prompt.mp3',
}),
submitResponse: vi.fn().mockResolvedValue(mockTutorResponse),
},
speech: {
recognize: vi.fn().mockResolvedValue({
transcript: 'Hola, como estas',
confidence: ,
}),
: vi.().({
: ,
: ,
: ,
: ,
}),
},
};
vi.(, ({
: vi.().( mockSpeakClient),
: vi.(),
: vi.(),
}));
Step 5: Write Unit Tests
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mockSpeakClient } from '../mocks/speak-mock';
import { SpeakService } from '../../src/speak/client';
describe('Speak Client', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('should initialize with API key', () => {
const service = new SpeakService({ apiKey: 'test-key', appId: 'test-app' });
expect(service).toBeDefined();
});
it('should verify health check', async () => {
const result = await mockSpeakClient.health.check();
expect(result.healthy).toBe(true);
});
it('should start a lesson session', async () => {
const session = await mockSpeakClient.tutor.startSession({
language: ,
: ,
});
(session.).();
(session.).();
});
(, () => {
feedback = mockSpeakClient..({
: ,
});
(feedback.).();
(feedback.).();
});
});
Step 6: Create Mock Lesson Runner
import { SpeakClient } from '@speak/language-sdk';
const isMockMode = process.env.SPEAK_MOCK_MODE === 'true';
export async function runMockLesson() {
if (isMockMode) {
console.log('Running in MOCK mode');
return {
prompt: 'Mock: Let\'s practice Spanish!',
feedback: { score: 85, message: 'Mock feedback' },
};
}
const client = new SpeakClient({
apiKey: process.env.SPEAK_API_KEY!,
appId: process.env.SPEAK_APP_ID!,
language: 'es',
});
}
Output
- Working development environment with hot reload
- Configured test suite with mocking
- Environment variable management
- Fast iteration cycle for Speak development
- Mock tutor for offline development
Error Handling
| Error | Cause | Solution |
|---|
| Module not found | Missing dependency | Run npm install |
| Port in use | Another process | Kill process or change port |
| Env not loaded | Missing .env.local | Copy from .env.example |
| Test timeout | Slow network | Use mocks or increase timeout |
| Audio not playing | Browser security | Use HTTPS in dev |
Examples
Mock Speech Recognition
export function createMockSpeechRecognizer() {
return {
start: vi.fn(),
stop: vi.fn(),
onResult: vi.fn(),
simulateResult: (text: string, score: number) => {
return {
transcript: text,
pronunciationScore: score,
timing: {
duration: 2500,
words: [
{ word: 'Hola', start: 0, end: 500, score: 90 },
{ word: 'como', start: 600, end: 1000, score: 85 },
{ word: 'estas', start: 1100, end: 1600, score: 80 },
],
},
};
},
};
}
Debug Mode with Verbose Logging
DEBUG=speak:* npm run dev
DEBUG=speak:speech npm run dev
DEBUG=speak:tutor npm run dev
Development Scripts
{
"scripts": {
"dev": "tsx watch src/index.ts",
"dev:mock": "SPEAK_MOCK_MODE=true tsx watch src/index.ts",
"test:unit": "vitest run tests/unit",
"test:integration": "vitest run tests/integration",
"lesson:spanish": "tsx src/lessons/spanish-basics.ts",
"lesson:korean": "SPEAK_TARGET_LANGUAGE=ko tsx src/lessons/korean-basics.ts"
}
}
Resources
Next Steps
See speak-sdk-patterns for production-ready code patterns.