lila/documentation/ai-context/00-project-overview.md

6.9 KiB
Raw Blame History

00 — Project Overview

Purpose: Give any LLM instant context on what Lila is, what makes it different, and what's currently built vs. planned. Concatenate this file with domain-specific files (0106) and 99-current-task.md before handing to an LLM. Last updated: 2026-05-15 Depends on: Nothing (this is the entry point)


What Lila Is

Lila is a vocabulary learning app with two core differentiators:

  1. Media-based practice — Users learn vocabulary extracted from real media they love: a Shakira song, the first chapter of Harry Potter, an episode of Breaking Bad. The app extracts vocabulary from subtitles/lyrics/text and turns it into quiz questions.
  2. Multiplayer modes — Users practice vocabulary together or competitively in real-time sessions (24 players, simultaneous answers, live scoring).

The core learning loop is Duolingo-style: a word appears in one language, the user picks the correct translation from four choices.

Live at lilastudy.com.


Current State (2026-05-15)

What Works Today

  • Singleplayer quiz — 5 language pairs (en↔it/de/es/fr), 3 or 10 rounds, POS + difficulty filters
  • Multiplayer — Create/join lobby by room code, 24 players, simultaneous answers, 15s server timer, live scoring, winner screen
  • Auth — Google + GitHub via Better Auth
  • Deployment — Live on Hetzner VPS, Caddy HTTPS, Docker Compose, CI/CD via Forgejo Actions
  • Database — PostgreSQL with Drizzle ORM, daily backups

What's In Progress / Blocked

  • Data pipeline rewrite — The Kaikki/local-LLM pipeline was replaced by a Gemini-only pipeline writing a new sense-based schema (wordssensestranslations). Schema and prompt are done; the pipeline script itself is not written yet. See 05-data-pipeline.md.
  • Guest play — No try-before-signup flow yet. Auth required for all game routes.
  • Game session store — Still in-memory. Valkey container exists locally but not wired up.
  • Media ingestion — Not started. No pipeline for subtitles/lyrics → vocab extraction yet.

The Strategic Gap

The app is currently a generic vocabulary quiz. The media-based practice feature (the differentiator) does not exist yet. It depends on:

  1. The new data pipeline reaching production (fixes translation quality)
  2. A media ingestion prototype (subtitles/lyrics → text → vocab extraction → quiz)

Tech Stack

Layer Technology
Monorepo pnpm workspaces
Frontend React 19, Vite, TanStack Router, Tailwind CSS
Backend Node.js, Express, TypeScript, WebSockets (ws library)
Database PostgreSQL + Drizzle ORM
Auth Better Auth (Google + GitHub)
Validation Zod (shared between frontend and backend in packages/shared)
Testing Vitest, supertest
Deployment Docker Compose, Caddy, Hetzner VPS
CI/CD Forgejo Actions
Data Pipeline Gemini API → SQLite staging (db/staging.db) → PostgreSQL

Repository Structure

lila/
├── apps/
│   ├── api/              — Express backend (HTTP + WebSocket)
│   └── web/              — React frontend (Vite, TanStack Router)
├── packages/
│   ├── shared/           — Zod schemas + constants (API/web contract)
│   └── db/               — Drizzle schema, migrations, models, seeding
├── data-pipeline/        — Gemini generation → SQLite staging → PostgreSQL
└── documentation/        — Project docs (human + AI-context branches)

Key rule: packages/shared is the single source of truth for all data shapes crossing the API boundary. Both frontend and backend import from it. If a schema changes, TypeScript compilation fails in both places simultaneously.


Key Architecture Principles

  1. Layered architecture — Router → Controller → Service → Model → Database. Each layer only talks to the layer below it.
  2. Server-side answer evaluation — The correct answer is never sent to the frontend. All evaluation happens server-side.
  3. Zod discriminated unions for WebSockets — All WS messages are typed via Zod schemas in packages/shared. The router switches on the type field.
  4. GameSessionStore abstraction — Session state is stored through an interface (InMemoryGameSessionStore now, ValkeyGameSessionStore planned).
  5. Sense-based data modelwords have senses, and translations hang off a sense. Adding a language requires no schema changes. Note the app still queries the older vocabulary_entries tables — see 02-data-model.md.

Key Decisions (Summary)

Topic Decision Why
ORM Drizzle, not Prisma No binary, no engine, closer to SQL
WebSocket ws library, not Socket.io 24 players, explicit Zod protocol sufficient
Auth Better Auth, not Keycloak Embedded middleware, no separate service
Answer eval Server-side only Correct answer never sent to frontend
Data source Gemini-generated, not OMW Sense-disambiguated, language-native glosses

Further Reading (AI-Context Files)

File What it covers
01-architecture.md Monorepo structure, layered architecture, data flow diagrams
02-data-model.md Database schema, tables, relationships, constraints
03-api-contract.md REST endpoints, request/response schemas, Zod types
04-websocket-protocol.md WS message types, game flow, auth, state management
05-data-pipeline.md Gemini pipeline flow, output contract, validation, blockers
06-deployment.md Docker, Caddy, CI/CD, backups
prompts/meta.md How to work with LLMs on this codebase
99-current-task.md Template: fill this out before giving a task to an LLM