# lila **Learn words. Beat friends.** lila is a vocabulary trainer built around a Duolingo-style quiz loop: a word appears in one language, you pick the correct translation from four choices. It supports singleplayer and real-time multiplayer, and is designed to work across multiple language pairs without schema changes. Live at [lilastudy.com](https://lilastudy.com). --- ## Stack | Layer | Technology | |---|---| | Monorepo | pnpm workspaces | | Frontend | React 18, Vite, TypeScript | | Routing | TanStack Router | | Server state | TanStack Query | | Styling | Tailwind CSS | | Backend | Node.js, Express, TypeScript | | Database | PostgreSQL + Drizzle ORM | | Validation | Zod (shared schemas) | | Auth | Better Auth (Google + GitHub) | | Realtime | WebSockets (`ws` library) | | Testing | Vitest, supertest | | Deployment | Docker Compose, Caddy, Hetzner VPS | | CI/CD | Forgejo Actions | --- ## Repository Structure ``` lila/ ├── apps/ │ ├── api/ — Express backend │ └── web/ — React frontend ├── packages/ │ ├── shared/ — Zod schemas and types shared between frontend and backend │ └── db/ — Drizzle schema, migrations, models, seeding scripts ├── scripts/ — Python scripts for vocabulary data extraction └── documentation/ — Project docs ``` `packages/shared` is the contract between frontend and backend. All request/response shapes are defined there as Zod schemas and never duplicated. --- ## Architecture Requests flow through a strict layered architecture: ``` HTTP Request → Router → Controller → Service → Model → Database ``` Each layer only talks to the layer directly below it. Controllers handle HTTP only. Services contain business logic only. Models contain database queries only. All database code lives in `packages/db` — the API never imports Drizzle directly for queries. --- ## Data Model Words are modelled as language-neutral concepts (`terms`) with per-language `translations`. Adding a new language requires no schema changes — only new rows. CEFR levels (A1–C2) are stored per translation for difficulty filtering. Core tables: `terms`, `translations`, `term_glosses`, `decks`, `deck_terms` Auth tables (managed by Better Auth): `user`, `session`, `account`, `verification` Vocabulary data is sourced from WordNet and the Open Multilingual Wordnet (OMW). --- ## API ``` POST /api/v1/game/start — start a quiz session (auth required) POST /api/v1/game/answer — submit an answer (auth required) GET /api/v1/health — health check (public) ALL /api/auth/* — Better Auth handlers (public) ``` The correct answer is never sent to the frontend — all evaluation happens server-side. --- ## Multiplayer Rooms are created via REST, then managed over WebSockets. Messages are typed via a Zod discriminated union. The host starts the game; all players answer simultaneously with a 15-second server-enforced timer. Room state is held in-memory (Valkey deferred). --- ## Infrastructure ``` Internet → Caddy (HTTPS) ├── lilastudy.com → web (nginx, static files) ├── api.lilastudy.com → api (Express) └── git.lilastudy.com → Forgejo (git + registry) ``` Deployed on a Hetzner VPS (Debian 13, ARM64). Images are built cross-compiled for ARM64 and pushed to the Forgejo container registry. CI/CD runs via Forgejo Actions on push to `main`. Daily database backups are synced to the dev laptop via rsync. See `documentation/deployment.md` for the full infrastructure setup. --- ## Local Development ### Prerequisites - Node.js 20+ - pnpm 9+ - Docker + Docker Compose ### Setup ```bash # Install dependencies pnpm install # Create your local env file (used by docker compose + the API) cp .env.example .env # Start local services (PostgreSQL, Valkey) docker compose up -d # Build shared packages pnpm --filter @lila/shared build pnpm --filter @lila/db build # Run migrations and seed data pnpm --filter @lila/db migrate pnpm --filter @lila/db seed # Start dev servers pnpm dev ``` The API runs on `http://localhost:3000` and the frontend on `http://localhost:5173`. --- ## Testing ```bash # All tests pnpm test # API only pnpm --filter api test # Frontend only pnpm --filter web test ``` --- ## Roadmap | Phase | Description | Status | |---|---|---| | 0 | Foundation — monorepo, tooling, dev environment | ✅ | | 1 | Vocabulary data pipeline + REST API | ✅ | | 2 | Singleplayer quiz UI | ✅ | | 3 | Auth (Google + GitHub) | ✅ | | 4 | Multiplayer lobby (WebSockets) | ✅ | | 5 | Multiplayer game (real-time, server timer) | ✅ | | 6 | Production deployment + CI/CD | ✅ | | 7 | Hardening (rate limiting, error boundaries, monitoring, accessibility) | 🔄 | See `documentation/roadmap.md` for task-level detail.