{"id":51500124,"url":"https://github.com/darth-dodo/habla-hermano","last_synced_at":"2026-07-07T17:30:46.419Z","repository":{"id":333604202,"uuid":"1132995204","full_name":"darth-dodo/habla-hermano","owner":"darth-dodo","description":"💬 AI Language Tutor for learning Spanish, German, and French through conversation","archived":false,"fork":false,"pushed_at":"2026-04-01T09:10:58.000Z","size":8645,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-01T11:18:46.680Z","etag":null,"topics":["ai","ai-agents","fastapi","langgraph","supabase"],"latest_commit_sha":null,"homepage":"https://habla-hermano.onrender.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darth-dodo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-12T18:28:13.000Z","updated_at":"2026-04-01T09:11:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/darth-dodo/habla-hermano","commit_stats":null,"previous_names":["darth-dodo/habla-hermano"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/darth-dodo/habla-hermano","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darth-dodo%2Fhabla-hermano","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darth-dodo%2Fhabla-hermano/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darth-dodo%2Fhabla-hermano/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darth-dodo%2Fhabla-hermano/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darth-dodo","download_url":"https://codeload.github.com/darth-dodo/habla-hermano/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darth-dodo%2Fhabla-hermano/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35237753,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-agents","fastapi","langgraph","supabase"],"created_at":"2026-07-07T17:30:46.353Z","updated_at":"2026-07-07T17:30:46.413Z","avatar_url":"https://github.com/darth-dodo.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Habla Hermano\n\n\u003e Your AI conversation partner for Spanish, German, and French.\n\n[![CI](https://github.com/darth-dodo/habla-hermano/actions/workflows/ci.yml/badge.svg)](https://github.com/darth-dodo/habla-hermano/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/darth-dodo/habla-hermano/graph/badge.svg)](https://codecov.io/gh/darth-dodo/habla-hermano)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)\n[![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)\n[![FastAPI](https://img.shields.io/badge/FastAPI-009688?logo=fastapi\u0026logoColor=white)](https://fastapi.tiangolo.com)\n[![LangGraph](https://img.shields.io/badge/LangGraph-1C3C3C?logo=langchain\u0026logoColor=white)](https://langchain-ai.github.io/langgraph/)\n[![Built with Claude](https://img.shields.io/badge/Built%20with-Claude-cc785c?logo=anthropic\u0026logoColor=white)](https://claude.ai)\n\n\nAn AI language tutor that gets you talking from day one. Built with FastAPI, LangGraph, and Claude -featuring real-time voice, adaptive scaffolding, 60 structured lessons, encrypted conversations, conversation threads, and five culture-inspired themes.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/hero-opening.png\" alt=\"Opening screen - Spanish A1\" width=\"270\"/\u003e\n  \u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"docs/screenshots/mobile-scaffolding-beach.png\" alt=\"Word bank and scaffolding for beach vocabulary\" width=\"270\"/\u003e\n\u003c/p\u003e\n\n---\n\n## The Problem\n\nMost language apps optimize for engagement (streaks, XP, leaderboards) while teaching vocabulary in isolation. Users ace flashcards but freeze in real conversations.\n\n**Habla Hermano inverts this.** You have real conversations from message one, even as a complete beginner. The AI adapts its language mix from 80% English (A0) to 95%+ target language (B1), with scaffolding that fades as you improve.\n\nThe pedagogical model is [Communicative Language Teaching](docs/product.md#pedagogical-approach): meaning over form, implicit correction over explicit grammar drills, contextual vocabulary over decontextualized memorization.\n\n---\n\n## How It Works\n\n### Conversations That Adapt\n\n| Level | Experience |\n|-------|-----------|\n| **A0** Complete Beginner | 80% English, target words introduced one at a time. Hermano celebrates every attempt. |\n| **A1** Beginner | 50/50 mix. Short sentences, translations when needed. |\n| **A2** Elementary | 80% target language. Past tense, longer exchanges. |\n| **B1** Intermediate | 95%+ target language. Idioms, subjunctive, real discussions. |\n\n### Scaffolding That Fades\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/mobile-conversation-beach.png\" alt=\"Beach conversation with vocabulary\" width=\"270\"/\u003e\n  \u0026nbsp;\u0026nbsp;\n  \u003cimg src=\"docs/screenshots/mobile-pronunciation-beach.png\" alt=\"Pronunciation tips for nadar and mar\" width=\"270\"/\u003e\n\u003c/p\u003e\n\nStuck? Beginners get contextual help: **hints**, **word banks** (tap to insert), and **sentence starters**. Made a mistake? Hermano recasts it naturally, then offers expandable grammar and pronunciation tips.\n\nFor A0, scaffolding appears automatically. By A2, you won't need it.\n\n### Voice Conversations\n\nType or tap the microphone to speak. Hermano understands both.\n\n- **Speech-to-text** via Deepgram Nova-3 with code-switching (mix English and target language naturally)\n- **Text-to-speech** -tap the play button on any response to hear native pronunciation\n- **Per-message speed control** -0.75x to 1.5x, with CEFR-aware defaults (slower for beginners)\n\n### 60 Structured Lessons\n\nBeyond freeform chat, Hermano teaches bite-sized lessons through natural conversation. Lessons open directly in the chat interface -no separate player, just a guided dialogue.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/lessons-svg-icons.png\" alt=\"Lesson catalog with SVG icons\" width=\"500\"/\u003e\n\u003c/p\u003e\n\n- 3 languages \u0026times; 4 CEFR levels \u0026times; 5 lessons each\n- Multiple choice, fill-in-the-blank, and translation exercises\n- LLM-evaluated answers with accent-preserving normalization\n- Checkpoint-aware resume -pick up where you left off\n\n### Conversation Threads\n\nAuthenticated users can maintain multiple independent conversations with Hermano.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/threads-mobile-sidebar-open.png\" alt=\"Thread sidebar open on mobile showing auto-titled threads\" width=\"270\"/\u003e\n\u003c/p\u003e\n\n- A sidebar drawer opens via the hamburger icon (available on all screen sizes)\n- Each thread is auto-titled by Claude Haiku after the first exchange, so your history is readable at a glance\n- Rename or delete any thread inline from the sidebar\n- Switching between threads happens client-side with no page reload\n- Guests use a single session; thread management requires an account\n\n### Learning Paths \u0026 Spaced Repetition\n\nStructured paths guide you from beginner to intermediate with clear progression through CEFR levels. The SM-2 spaced repetition algorithm tracks every word you learn and weaves due vocabulary back into conversations at optimal intervals -no flashcard decks, just natural reinforcement during chat.\n\n### Five Themes\n\nFive culture-inspired themes with WCAG AA contrast compliance across all color tokens:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/theme-azulejo.png\" alt=\"Azulejo\" width=\"150\"/\u003e\n  \u0026nbsp;\n  \u003cimg src=\"docs/screenshots/theme-terracotta.png\" alt=\"Terracotta\" width=\"150\"/\u003e\n  \u0026nbsp;\n  \u003cimg src=\"docs/screenshots/theme-flamenco.png\" alt=\"Flamenco\" width=\"150\"/\u003e\n  \u0026nbsp;\n  \u003cimg src=\"docs/screenshots/theme-sangria.png\" alt=\"Sangria\" width=\"150\"/\u003e\n  \u0026nbsp;\n  \u003cimg src=\"docs/screenshots/theme-jardin.png\" alt=\"Jardin\" width=\"150\"/\u003e\n\u003c/p\u003e\n\n| Theme | Palette |\n|-------|---------|\n| **Azulejo** | Cool Mediterranean blue, warm sand backgrounds |\n| **Terracotta** | Warm earth tones, dark mode default |\n| **Flamenco** | Sunset reds and warm amber |\n| **Sangria** | Deep berry reds, rich plum accents |\n| **Jardin** | Mint green light theme for daytime learning |\n\n### Guest Access \u0026 Accounts\n\nNo sign-up required. Start chatting immediately as a guest -full conversation with Hermano, grammar feedback, scaffolding, and voice all work out of the box.\n\nCreate an account to unlock:\n- **Vocabulary tracking** -words you learn are saved and reviewed via SM-2 spaced repetition\n- **Progress dashboard** -visualize your learning journey with analytics charts, language filters, and detailed stats\n- **Conversation threads** -maintain multiple independent conversations with per-thread language and level\n- **Password reset** -forgot your password? Reset it via email through Supabase Auth\n- **Account deletion** -delete your account and all associated data (vocabulary, sessions, checkpoints)\n\n### Privacy \u0026 Encryption\n\nAll conversations are encrypted at rest with Fernet (AES-128-CBC + HMAC-SHA256). User PII fields use field-level encryption, and LangGraph checkpoint blobs are encrypted with a dedicated cipher. Row-level security policies ensure users can only access their own data.\n\n---\n\n## For Developers\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eTech Stack \u0026 Architecture\u003c/strong\u003e\u003c/summary\u003e\n\n### Tech Stack\n\n| Layer | Technology | Why |\n|-------|-----------|-----|\n| **Backend** | FastAPI | Async SSE streaming, Pydantic validation, WebSocket support |\n| **Agent** | LangGraph | Stateful conversation graphs with conditional routing and checkpointing |\n| **LLM** | Claude (Haiku 4.5) | Strong multilingual understanding, structured output for exercises |\n| **Frontend** | HTMX + Alpine.js + Tailwind | Server-rendered, no SPA complexity, 11 ES modules |\n| **Database** | PostgreSQL (Supabase) | Row-level security, auth, real-time. Local SQLite fallback |\n| **Auth** | Supabase Auth | JWT with httponly cookies, guest sessions via signed UUIDs |\n| **Voice** | Deepgram (Nova-3 STT, Aura-2 TTS) | FSM-driven WebSocket streaming with AbortController cancellation |\n| **Encryption** | cryptography (Fernet) | Field-level + checkpoint blob encryption, PBKDF2 key derivation |\n| **Monitoring** | Sentry | Error tracking and performance monitoring (backend + frontend) |\n| **Lessons** | 60 YAML files | 3 languages \u0026times; 4 CEFR levels \u0026times; 5 lessons, ~6,300 lines of content |\n| **Testing** | pytest + Vitest | 2,529 tests (2,291 Python + 238 JS), 97% coverage, strict mypy, ruff linting |\n\n### System Overview\n\n```mermaid\ngraph LR\n    B[\"Browser\u003cbr/\u003e(HTMX + Alpine.js + ES Modules)\"]\n    F[\"FastAPI\"]\n    LG[\"LangGraph Pipeline\"]\n    C[\"Claude API\"]\n    DG_STT[\"Deepgram Nova-3 STT\"]\n    DG_TTS[\"Deepgram Aura-2 TTS\"]\n    DB[\"Supabase (PostgreSQL)\"]\n\n    B -- \"SSE POST /chat/stream\" --\u003e F --\u003e LG --\u003e C\n    B -- \"WebSocket /ws/transcribe\" --\u003e F -- \"WS Proxy\" --\u003e DG_STT\n    B -- \"WebSocket /ws/speak\" --\u003e F -- \"WS Proxy\" --\u003e DG_TTS\n    B -- \"HTMX requests\" --\u003e F -- \"Jinja2 SSR\" --\u003e DB\n```\n\n### LangGraph Conversation Engine\n\nThe core is a **stateful LangGraph pipeline** with conditional routing. Each user message traverses a graph that decides what feedback to generate:\n\n```mermaid\ngraph TD\n    A[\"User Message\"] --\u003e R[\"respond\u003cbr/\u003eGenerate AI response (Claude Haiku)\"]\n    R --\u003e S{\"should_scaffold?\u003cbr/\u003eCEFR level + message analysis\"}\n    S -- yes --\u003e SC[\"scaffold\u003cbr/\u003eWord bank, hints, sentence starters\"]\n    S -- no --\u003e AN\n    SC --\u003e AN{\"should_analyze?\u003cbr/\u003eDid the user make errors?\"}\n    AN -- yes --\u003e AZ[\"analyze\u003cbr/\u003eGrammar corrections + pronunciation tips\"]\n    AN -- no --\u003e W\n    AZ --\u003e W{\"should_weave_review?\u003cbr/\u003eSM-2 spaced repetition check\"}\n    W -- yes --\u003e WV[\"weave\u003cbr/\u003eInsert due vocabulary naturally\"]\n    W -- no --\u003e E[\"END\u003cbr/\u003eStream all outputs via SSE\"]\n    WV --\u003e E\n```\n\n**Key design decisions**:\n- **Conditional edges over sequential chains**: Scaffolding and analysis only run when needed, reducing latency and API costs for advanced learners\n- **State as TypedDict with reducers**: `add_messages` reducer for conversation history, explicit fields for `grammar_feedback`, `scaffolding`, `new_vocabulary`\n- **Separate lesson subgraph**: Conversational lessons use a dedicated LangGraph with a 5-phase state machine (intro → teaching → exercise_ask → exercise_eval → complete) with LLM-based answer evaluation\n- **Checkpointing**: PostgreSQL-backed `AsyncPostgresSaver` with encrypted serialization in production, `MemorySaver` for local dev\n\n### Streaming Architecture\n\nResponses stream token-by-token via **Server-Sent Events** (POST to `/chat/stream`):\n\n| SSE Event | Payload | Client Action |\n|-----------|---------|---------------|\n| `token` | `{content}` | Append to bubble, throttled scroll (every 3 tokens) |\n| `response_complete` | `{content, rendered_html}` | Finalize bubble with server-rendered markdown |\n| `scaffolding` | `{html}` | Insert collapsible help section |\n| `grammar` | `{html}` | Insert grammar correction panel |\n| `lesson_progress` | `{progress, phase}` | Update segmented progress indicator |\n| `done` | `{}` | Re-enable input |\n\n### Voice Pipeline\n\nVoice is optional. The app degrades gracefully without Deepgram keys.\n\n**STT**: Browser captures audio via `AudioWorklet` (PCM16 at 16kHz), streams over WebSocket to a FastAPI proxy forwarding to Deepgram Nova-3 with interim results and endpoint detection.\n\n**TTS**: Per-message play button opens a WebSocket to `/ws/speak`, sends text, receives linear16 PCM chunks, decodes to Float32, plays via `AudioBufferSourceNode` on a shared `AudioContext` (reused to avoid Safari's 4-instance limit). CEFR-aware speed defaults (A0=0.75x, A1=0.85x, A2/B1=1x).\n\n**iOS Safari**: `AudioContext.state` can report `'running'` while silently refusing output. Fix: always call `resume()` on every gesture, plus `AbortController` per session to prevent stale WebSocket handlers from corrupting active sessions.\n\n### Design System\n\nFive themes built on CSS custom properties with a shared token architecture:\n\n- **Typography**: Plus Jakarta Sans (warmer than Inter, near-identical metrics)\n- **Spacing tokens**: `--space-chat-gap`, `--space-bubble-pad`, `--radius-bubble`, etc.\n- **Icons**: Lucide SVG icons replacing emoji indicators throughout\n- **Animations**: `vocabHighlight`, `levelBadgePop`, `progressShimmer`, `confettiBurst`\n- **Accessibility**: WCAG AA contrast on all themes, `aria-live` regions, focus-visible rings\n\n### Frontend Modules\n\nServer-rendered HTML (Jinja2 + HTMX) with 11 ES modules:\n\n| Module | Responsibility |\n|--------|---------------|\n| `stream.js` | SSE client, streaming bubble management, lesson progress events |\n| `voice.js` | Voice orchestrator: wires FSM services, owns mutable state, public API |\n| `voice-constants.js` | Voice config: sample rates, Deepgram voice IDs, SVG icons, audio utilities |\n| `voice-stt.js` | STT state machine, mic capture via AudioWorklet, WebSocket transcript streaming |\n| `voice-tts.js` | TTS state machine, WebSocket PCM streaming, REST fallback, AudioContext playback |\n| `voice-ui.js` | Stateless voice UI helpers: recording indicators, timers, tooltips |\n| `fsm.js` | Generic finite state machine: `createMachine` + `interpret` with onChange listeners |\n| `dom.js` | Scroll management, focus, message rendering, HTML escaping |\n| `scaffold.js` | Click-to-insert word bank, collapsible help sections |\n| `shortcuts.js` | Keyboard shortcuts (`/` to focus, `Shift+Enter` for newline) |\n| `htmx-handlers.js` | HTMX lifecycle event handlers: after-swap scroll, error display |\n\n### Project Structure\n\n```\nsrc/\n├── agent/           LangGraph graphs, nodes, prompts (freeform + lesson subgraphs)\n├── api/             FastAPI routes, auth, middleware, streaming, rate limiting\n├── db/              Supabase client, repository pattern, models, encryption\n├── services/        Business logic (review/SM-2, lesson completion, adaptive paths, thread management)\n├── lessons/         Lesson models and YAML loader\n├── templates/       Jinja2 with HTMX partials\n└── static/          CSS + 11 ES modules + AudioWorklet processor\n\ndata/lessons/        60 YAML lesson files (es/, de/, fr/)\ntests/               2,291 pytest + 238 Vitest tests\ndocs/                Architecture, API reference, design docs, ADRs\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSecurity\u003c/strong\u003e\u003c/summary\u003e\n\n| Layer | Implementation |\n|-------|---------------|\n| **Encryption at rest** | Fernet (AES-128-CBC + HMAC-SHA256) for PII fields + LangGraph checkpoint blobs |\n| **Row-Level Security** | Checkpoint tables enforce user isolation via `checkpoint_owner()` policies |\n| **CSP** | Nonce-based `script-src`, no `'unsafe-inline'` |\n| **CSRF** | Custom-header pattern (`X-Requested-With` / `HX-Request`) via middleware |\n| **WebSocket Auth** | JWT validated from cookies before `accept()`, reject with 4001 |\n| **Rate Limiting** | Decorator-based for REST, sliding-window per-connection for WebSocket |\n| **XSS** | `nh3` sanitization + `markupsafe.escape()` for all user content |\n| **Cookies** | Signed with `itsdangerous`, environment-aware `Secure` flag |\n| **Headers** | HSTS, X-Frame-Options, X-Content-Type-Options, `Cache-Control: no-store` on auth pages |\n| **CORS** | Explicit `allow_headers` allowlist -no wildcard |\n| **Thread ownership** | `thread_id` ownership verified server-side before any chat operation |\n| **Password reset** | Supabase Auth email recovery with client-side token extraction and server-side session establishment |\n| **Error monitoring** | Sentry integration (backend + frontend) for error tracking and performance monitoring |\n\nSee [Architecture → Security](docs/architecture.md) for the full threat model.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eTesting\u003c/strong\u003e\u003c/summary\u003e\n\n**2,291 Python tests** (pytest) + **238 JavaScript tests** (Vitest) with CI on every push.\n\n| Domain | What's Tested |\n|--------|---------------|\n| Agent | LangGraph node behavior, conditional routing, state mutations, prompt injection |\n| API | Every route (chat, lessons, auth, voice, progress), CSRF, rate limiting |\n| Services | SM-2 algorithm, lesson completion, adaptive paths, review scheduling |\n| Database | Repository pattern, encryption boundary (encrypt-on-write, decrypt-on-read) |\n| JavaScript | All 11 ES modules: DOM, streaming, scaffolding, shortcuts, voice (FSM + sub-modules) |\n| Security | CSP nonce injection, WebSocket auth rejection, header verification, Fernet round-trip, thread ownership, auth cache headers, password reset flow |\n| Integration | Voice WebSocket transport, SSE streaming end-to-end |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eQuick Start\u003c/strong\u003e\u003c/summary\u003e\n\n**Live demo**: [habla-hermano.onrender.com](https://habla-hermano.onrender.com) — no setup needed, start chatting immediately.\n\n**Run locally**:\n\n```bash\ngit clone https://github.com/darth-dodo/habla-hermano.git\ncd habla-hermano\nmake install\n\ncp .env.example .env\n# Add your ANTHROPIC_API_KEY to .env\n# Optional: DEEPGRAM_API_KEY for voice, SUPABASE_URL + keys for auth/persistence\n\nmake dev\n```\n\nOpen [http://localhost:8000](http://localhost:8000). No account required. Guest sessions work out of the box.\n\n**Requirements**: Python 3.12+, [uv](https://docs.astral.sh/uv/)\n\n**Development commands**: `make dev` | `make test` | `make check` (lint + typecheck) | `make clean`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDocumentation\u003c/strong\u003e\u003c/summary\u003e\n\n| Doc | Content |\n|-----|---------|\n| [Architecture](docs/architecture.md) | LangGraph pipeline, data flow, security model, voice architecture |\n| [Product Vision](docs/product.md) | Pedagogical approach, CEFR progression, personality system |\n| [API Reference](docs/api.md) | All endpoints, WebSocket protocols, SSE event spec |\n| [Design System](docs/design/design-system.md) | Token architecture, typography, spacing, themes, animations |\n| [Testing](docs/testing.md) | Test strategy, mock patterns, coverage targets |\n| [Codebase Summary](docs/codebase-summary.md) | Onboarding guide for the full codebase |\n| [Changelog](CHANGELOG.md) | Release history across 27 phases |\n\n#### Design Documents\n\n| Phase | Design |\n|-------|--------|\n| Micro-Lessons | [Phase 6](docs/design/phase6-micro-lessons.md) |\n| Spaced Repetition | [Phase 12](docs/design/phase12-spaced-repetition.md) |\n| Mobile Responsive | [Phase 13](docs/design/phase13-mobile-responsive.md) |\n| Learning Paths | [Phase 14](docs/design/phase14-learning-paths.md) |\n| SSE Streaming | [Phase 15](docs/design/phase15-sse-streaming.md) |\n| ES Module Refactor | [Phase 16](docs/design/phase16-esm-refactor.md) |\n| Voice Conversation | [Phase 17](docs/design/phase17-voice-deepgram.md) |\n| Conversational Lessons | [Phase 19](docs/design/phase19-conversational-lessons.md) |\n| Spanish Themes | [Phase 20](docs/design/phase20-spanish-themes.md) |\n| Voice FSM Refactor | [Phase 21](docs/design/phase21-voice-fsm-refactor.md) |\n| Message Encryption | [Phase 24](docs/design/phase24-message-encryption.md) |\n| Design System Revamp | [Phase 25](docs/design/phase25-design-system-revamp.md) |\n| Conversation Threads | [Phase 26](docs/design/phase26-conversation-threads.md) |\n| Privacy \u0026 Security Page | [Phase 27](docs/design/phase27-privacy-security-page.md) |\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarth-dodo%2Fhabla-hermano","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarth-dodo%2Fhabla-hermano","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarth-dodo%2Fhabla-hermano/lists"}