New "Rébus" mode: guess the geek work from an emoji puzzle (free-text answer,
tolerant matching). Implemented as a quiz format `rebus` — reuses the whole quiz
machinery (pool, anti-repeat, speed scoring, recap, bots, back-office):
- shared: QuizFormat/GameType/MixMode + RoundConfig.pool gain "rebus"
- server: rebus is a text format; pool composes a rebus sub-pool (not filtered by
category); ~9 seeded emoji rebus in the in-code bank; admin accepts the format
- client: lobby tile + sub-mode + count; big centered emoji display in the round;
dedicated transition theme (🧩 RÉBUS); FR/EN strings; back-office form option
Verified e2e: a rebus game serves only rebus rounds with emoji prompts and the
recap shows the right answers. typecheck/lint/build/24 tests green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- curated, bilingual player-facing notes (lib/patch-notes.ts) — a public subset
of CHANGELOG.md (which stays the technical source of truth)
- "Nouveautés" button on home with a dot badge when the app version changed
since last seen (localStorage); opening marks the version seen
- app version injected at build via Vite define (__APP_VERSION__)
- add shadcn Dialog component (@workspace/ui, via radix-ui)
Verified: notes + version baked into the build; typecheck/lint/build green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Playtest feedback round 2:
- blindtest DJ can now be anyone incl. the track's contributor (pickDj only
excludes bots) — no more "immunity" for whoever isn't picked
- blindtest rounds last 90s (longer listen + typing)
- per-player volume slider (persisted), YT player setVolume + origin/enablejsapi
- theme switcher (light/dark/system) on home + room header
- clock sync: clients estimate the server-clock offset (time:sync) so the
countdown is identical across devices (was off by each device's clock skew);
also used for blindtest media sync
Note on duplicates: anti-repeat is per room code (quiz_played) — it works when
you replay in the SAME room, but a new room starts fresh. Verified e2e: two
chained games in one room share 0 questions.
Verified: typecheck 4/4, lint 4/4, 24 server tests, web build; e2e dedup (0
overlap) and clock/DJ behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From friends playtest feedback:
- blindtest "who added it?" (and mixed): hide the per-player vote status — the
contributor never validates, which gave them away
- blindtest sound: set YT player `origin`/`enablejsapi` (fixes the postMessage
origin warning) and add a per-game "Activer le son" gesture for non-DJ
(browsers block audible autoplay without a user gesture)
- track list: render each player's own tracks from a server-sent, authoritative
blindtest:myTracks event (emitted on submit/remove/reconnect) instead of local
state that desynced on remount — fixes the "3/3 but only 2 shown" case
- quiz: reset the free-answer input between questions (was pre-filled with the
previous answer)
Verified e2e: myTracks emitted on submit + reconnect.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- lightweight, dependency-free i18n: typed fr/en dictionaries (fr is the source
of truth, en must match its shape → compile error on drift), I18nProvider +
useI18n hook, browser detection + localStorage persistence
- FR/EN language switcher (home + room header)
- translated the whole player-facing flow: home, join, pseudo, room shell,
lobby (incl. settings, categories, bots, track submission, history),
quiz, blindtest, player-cards, round transitions, end screen (podium, awards,
tracks, rounds recap), and server-error messages (mapped by code)
- history dates localized to the active language
Content (questions/categories) intentionally left as-is. Back-office (admin)
not translated yet — internal, token-gated tool.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>