A real-time, multiplayer vocabulary game for German language classes. One player describes a German word without saying it, everyone else races to hit the buzzer first. Players join from their phones by typing a name — no accounts, no installs.
I built it for my own German course, and it's used in class: the teacher picks the chapters, the game runs on everyone's phone, and the scoreboard does the rest.
Stack: Node.js · Express 5 · Socket.IO · vanilla JS (PWA) · Claude API (structured output) · Docker
The design decisions behind the rules, scoring and deployment are written up in
docs/DESIGN.md.
A round from start to finish, as seen on phones (the UI is in German, the language of the class):
| Lobby (teacher) | Who goes first? | Explainer's card | Everyone else |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
| Judging (teacher) | Scoreboard | Podium | Word management |
![]() |
![]() |
![]() |
![]() |
The card on the explainer's phone never reaches the other players: they only get the article and word type, so the word can't be read from network traffic either.
- Live buzzer over WebSockets — the first press is locked server-side and broadcast to every screen, so there are no race conditions between phones.
- Server-authoritative game state machine —
lobby → picking → explaining → buzzed → finished; timers, round limits and turn order all run on the server, so a phone going to sleep can't stall the game. - Need-to-know data delivery — the word card is sent only to the explainer and the teacher. Hidden hints (articles) are never sent to clients that shouldn't see them, so they can't be read from network traffic.
- Roles without accounts — teacher (admin) and developer roles are resolved from a configured name; the developer account can be password-protected and sees player feedback.
- Helper-word generation with the Claude API — an optional server endpoint (
POST /api/generate) generates word cards in batches using a zod schema and structured output, at import time, not during play: zero latency in class, works offline, and cards can be reviewed before the lesson. The in-app button was later removed; cards are now entered in the admin UI or imported from JSON. - Book → chapter word bank with an admin UI for adding and editing words, plus a CLI importer (
scripts/import-words.jsvalidates articles, word types and duplicates before writing). - Tuned scoring — scoring rules were chosen by simulating 3,000 games with the real game engine (
scripts/simulate-scoring.js); e.g. lowering the wrong-answer penalty from 99 to 50 dropped the "worth buzzing" confidence threshold from ~50% to ~33% without hurting fairness. - Installable PWA, works on any phone browser; UI in German.
npm install
cp .env.example .env # optional: set names, owner password, API key
npm start # http://localhost:3000A 20-word sample chapter is seeded on first start. Type lehrer (configurable via ADMIN_NAME) to join as the teacher.
docker compose up -d --buildThe container binds to 127.0.0.1 only and is meant to sit behind a reverse proxy. Socket.IO needs the Upgrade/Connection headers forwarded — see the nginx example in docs/DESIGN.md. Word data lives in a named volume (taboo-data).
| Variable | Purpose |
|---|---|
ADMIN_NAME |
Name that joins as the teacher (default lehrer) |
OWNER_NAME / OWNER_PASSWORD |
Developer account; sees player feedback. npm run set-password writes the password to .env without echoing it |
ANTHROPIC_API_KEY |
Optional — enables AI helper-word generation |
ANTHROPIC_MODEL |
Model used for generation |
PORT / HOST_PORT |
App port / host port for Docker |
npm test # game engine + static checks (73 tests)
PORT=3100 npm start & PORT=3100 npm run test:live # Socket.IO end-to-end against a running server
npm run test:ui # browser E2E with puppeteer-core (needs a local Chrome)server/
index.js Express + Socket.IO, admin API, sessions and roles
game.js Game state machine, scoring, per-role visibility
store.js Word store (data/words.json)
feedback.js Player feedback with rate limiting
ai.js Helper-word generation with Claude (structured output)
parse.js Free-text word list parser
public/ Single-page client (PWA)
scripts/ Import, seeding, scoring simulation and test suites
data/ Seed data and chapter word lists
docs/ Design notes and screenshots
MIT







