Open source, self-hosted, Dockerized web application for learning languages with AI. A local language model (Ollama) evaluates your CEFR level, generates a personalized study plan, and guides you through grammar, vocabulary, reading comprehension, and writing lessons.
The study plan follows a CEFR-aligned curriculum (A1-C2) organized into units with clear competencies and prerequisites. After a deterministic placement assessment, FreeLingo creates a weekly roadmap based on your selected intensity (4, 8, 12, or 16 weeks), then unlocks lessons in sequence: grammar, vocabulary, reading, writing, and review.
The platform combines structure and adaptation: lessons are generated within curriculum boundaries, flashcards use SM-2 spaced repetition, and the AI tutor provides contextual streaming feedback in English (with optional brief support in the learner's native language). Progress tracking includes XP, streaks, skill scores, unit competencies, and an end-of-level completion test.
Monorepo: backend/ (Python FastAPI) + frontend/ (Next.js 16 App Router)
deployed via Docker Compose with PostgreSQL 16 and Redis 7.
The backend proxies all external services (Ollama, Kokoro, Whisper) —
the frontend never calls them directly.
freelingo/
├── assets/ # Logos and static assets
├── backend/ # FastAPI (Python)
├── docker/ # Custom Dockerfiles (e.g. Kokoro with Blackwell GPU support)
├── docs/ # GitHub Pages landing site
├── frontend/ # Next.js (React)
├── messages/ # i18n translation files (en, es, fr, pt, de, it)
├── specs/ # Specification files
├── AGENTS.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
└── docker-compose.yml
| Layer | Technology |
|---|---|
| Frontend | Next.js 16+, shadcn/ui, Tailwind CSS, Zustand, next-intl |
| Backend | FastAPI, SQLAlchemy async, Alembic, Pydantic v2 |
| Database | PostgreSQL 16 |
| Cache | Redis 7 |
| LLM | Ollama (local) · OpenAI · Anthropic · DeepSeek |
| TTS (P2) | Kokoro-FastAPI |
| STT (P2) | faster-whisper |
| Auth | JWT (access + refresh), multi-user, roles (admin/user). |
| Deploy | Docker Compose |
| Phase | Name | Status |
|---|---|---|
| 1 | Learning platform | ✅ Complete |
| 1+ | Learning Resources Hub | ✅ Complete |
| 2 | Local TTS + STT | ✅ Complete |
| 3 | Real-time conversation | 🚧 In progress |
Requirements: Docker, Docker Compose, Git, and Ollama running on the host.
# 1. Clone the repository
git clone https://github.com/artcc/freelingo.git
cd freelingo
# 2. Configure environment
cp .env.example .env
# Edit .env: set OLLAMA_BASE_URL, choose your model, and review other settings
# 3. Pull the recommended model (run on the host, not inside Docker)
ollama pull gemma3:12b
# 4. Start all services (migrations run automatically on first start)
docker compose up -dAccess at http://localhost:3000 (or http://<server-ip>:3000).
The first registered user becomes admin automatically.
- Open Portainer → Stacks → Add stack.
- Choose Repository and enter the repo URL, or paste the contents of
docker-compose.ymldirectly into the Web editor. - Scroll down to Environment variables and add the variables from
.env.example(at minimum:SECRET_KEY,OLLAMA_BASE_URL,POSTGRES_PASSWORD). - Click Deploy the stack.
- Access the app at
http://<server-ip>:3000. Database migrations run automatically when the backend starts.
Tip: If Ollama runs on the same host as Portainer, set
OLLAMA_BASE_URL=http://host.docker.internal:11434. On Linux you may need to add theextra_hostsentry in the compose file (already included by default).
- architecture.instructions.md — DB models, API endpoints, LLM adapter, auth design, code standards, test config
- CHANGELOG.md — Project changelog
- changelog.instructions.md — Changelog format, entry style, and update rules
- docker.instructions.md — Docker Compose by phase,
.env.example, DB migrations, operational notes - llm-error-handling.instructions.md — LLM failures: malformed JSON, timeouts, retries, context overflow
- phase-1-platform.instructions.md — Phase 1: scaffolding through frontend, prompts, SM-2, SSE chat
- phase-1-plus.instructions.md — Phase 1+: Learning Resources Hub — Grammar Reference, Vocabulary Hub, Phrasebook, Skills Tracker, Level Completion Test
- phase-2-tts-stt.instructions.md — Phase 2: Kokoro TTS, faster-whisper STT, pronunciation exercises
- phase-3-conversation.instructions.md — Phase 3: WebSocket voice pipeline, VAD, barge-in
- phase-4-grammar-reference.instructions.md — Phase 4: extended grammar reference and content pipeline
- rate-limiting.instructions.md — slowapi-based rate limits per-endpoint, self-hosted defaults
- readme.instructions.md — README structure, badges, and update guidelines
- roadmap.instructions.md — Development roadmap with milestones and completion criteria
- testing.instructions.md — Testing strategy: pytest, Vitest, Playwright, mocks, CI
- The recommended model for Ollama is
gemma3:12b. It can be changed in.env. - The backend acts as a proxy for Ollama/TTS/STT calls so the frontend never talks directly to those services.
- The
LLM_PROVIDERfield controls the LLM provider:ollama(local, recommended),openai,anthropic, ordeepseek. - The target language is always English. During registration, the user's native language is asked for flashcard translations and tutor feedback.
TTS (Kokoro) and STT (faster-whisper) are disabled by default. Both services are already defined in docker-compose.yml (commented out) and can be activated on either a GPU or a CPU host.
- The
kokoroandwhisperservices are already configured indocker-compose.ymlwith the NVIDIAdeployblock. - The Kokoro image (
ghcr.io/artcc/kokoro-fastapi-gpu) ships with PyTorch 2.7+ (cu128), supporting all NVIDIA architectures including Blackwell (RTX 5000 series, sm_120). - Add to
.env:TTS_ENABLED=true STT_ENABLED=true
- Restart the stack:
docker compose up -d.
-
Uncomment the
kokoroandwhisperservices indocker-compose.yml. -
Replace the image tags and remove the
deployblock for each service:Kokoro (TTS):
kokoro: image: ghcr.io/remsky/kokoro-fastapi-cpu:latest restart: unless-stopped ports: - "8880:8880"
Whisper (STT):
whisper: image: onerahmet/openai-whisper-asr-webservice:latest restart: unless-stopped ports: - "9000:9000" environment: - ASR_MODEL=base - ASR_ENGINE=faster_whisper
Use
ASR_MODEL=baseorsmallon CPU. Larger models (medium,large) are very slow without a GPU. -
Add to
.env:TTS_ENABLED=true STT_ENABLED=true
-
Restart the stack:
docker compose up -d.
- If TTS or STT is disabled, the backend returns
503on those endpoints. The frontend gracefully degrades: the listen/record buttons are not rendered. - The TTS voice can be changed via
TTS_VOICEin.env(default:af_heart). Available voices:af_heart,af_sky(American),bf_emma,bm_george(British). - The STT model is controlled by
ASR_MODELinside the whisper container environment variable, not from.env.
See CONTRIBUTING.md for guidelines on reporting bugs, suggesting features, and submitting pull requests.
Distributed under the Apache 2.0 License.
Arturo Carretero Calvo — @artcc
