DB:
- quiz_question gains `lang` ('fr' default) and `active` (true default); migration 0002
- only active questions are served to games (pool filter)
History:
- engine writes a game_history row at game end (modes + ranked results), fire-and-forget
- public GET /api/history/:code lists a room's recent games
- lobby shows a "Parties précédentes" collapsible (date, modes, winner/scores)
Back-office:
- create form has a FR/EN language select; lang stored
- per-question active toggle (PATCH /questions/:id) — disable without deleting;
inactive rows dimmed and labelled
- seeds set lang (opentdb=en, manual/pokemon=fr)
Verified e2e: migration applied; game played → /api/history returns it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- settings carry `categories` (empty = all); quiz/image pool filters by category
(DB + in-code bank), threaded through prepareQuizForRoom/loadGroup/loadQuizPool
- public GET /api/categories lists available categories
- lobby: category chips (Toutes + each), shown when quiz/images is active
- shared: RoomSettings.categories + UpdateSettingsPayload
Verified e2e: /api/categories returns the list; filtering by ["Pokémon"] serves
only Pokémon questions.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mixed settings fix:
- RoundConfig carries a `pool` hint (quiz | image) per quiz round; lobby shows
a separate count for each selected sub-mode (Quiz, Images) and the blindtest
config — not just the quiz one
- server pool composes the queue per round's pool (quiz formats vs image_reveal),
in order; verified e2e (2 quiz + 2 images honored)
Awards:
- "⚡ Le plus rapide" — derived client-side from the speed bonus baked into
quiz/image points (points above the 100 base on correct answers)
Desktop restyle:
- room page gets an ambient halo background and a responsive container
(lobby max-w-3xl with a 2-column players|settings grid, game/end max-w-lg)
- game/end views widened to max-w-lg
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- image_reveal display: larger, object-contain (whole image up to 58vh), no crop
- image prompt optional in back-office (defaults to "Qui est-ce ?"), overridable
- mixed mode reworked: select "Mixte" then toggle sub-modes (Quiz/Images/
Blindtest). Blindtest sub-mode locked under 3 players; mixed itself no longer
needs 3. Server quiz pool formats derived from gameType + mixedModes.
shared: MixMode + RoomSettings.mixedModes (default quiz+image).
- DB: prompt uniqueness is now a partial index (excludes image_reveal) + unique
index on image_url; lets many images share the generic prompt, dedup by URL.
- seed: db:seed:images pulls Pokémon (PokéAPI) as image_reveal questions with
official artwork (remote URL) + FR/EN accepted answers; idempotent by image_url.
Verified: migration applied, Pokémon seed inserts FR+EN, image mode serves only
image_reveal, all checks green (23 tests).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- image_reveal becomes its own game mode: GameType gains "image"; the quiz
pool is filtered by allowed formats derived from gameType (image →
image_reveal only, quiz → mcq/truefalse/free, mixed → all). loadQuizPool
takes a formats list; pool fallback respects it.
- lobby settings reworked into a refined "Réglages" card: 4 mode tiles
(icon + label, locked <3 players for blindtest/mixed), question count as a
stepper, blindtest config grouped; dynamic label for image mode + hint.
- admin: real upload button (hidden input + styled Button with Upload icon)
instead of the bare file input.
- app title set to "NerdWare …" in index.html (+ lang fr, description).
Verified e2e: image mode serves only image_reveal questions (with imageUrl).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- "Ajouter" button shows the SiYoutube logo
- each submitted track card gets a YouTube open link (verify the pasted song)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- blindtest/mixed: the host can't start until every connected player has
submitted their track quota — client disables the button with a hint, and
game:start rejects with TRACKS_PENDING (authoritative)
- tracks-per-player is now a number stepper (− / + buttons + free typing,
clamped 1..10) instead of fixed 1/2/3 buttons
Verified e2e: start rejected while a player hasn't submitted, accepted once all did.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- game:end now carries the played blindtest tracks (title/artist/youtubeId/
url/submittedByName); the end screen lists them as cards with a YouTube
open link so players can recover/export the songs
- who_added vote no longer lets you pick yourself (filtered out)
- home page: animated halo, floating geek emojis, springy gradient title,
hover/tap on buttons (Framer Motion) + Lucide icons
- lobby settings get Lucide icons (game type, quiz, blindtest mode, tracks,
start)
Verified e2e: game:end includes the track list with links.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Return to lobby (replay without recreating the room):
- lobby:return (host): reset to lobby, scores to 0, keep players + tracks
- client: end screen has "Rejouer" (host) + "Quitter"; store clears transient
game state whenever the room goes back to lobby
Contributor has nothing to input:
- round:start carries a private `mine: true` to the contributor only (via
RoundStart.secretPlayerId targeted emit); they're excluded from eligible
voters. Client shows a "fais-les se tromper" card instead of the vote form.
Editable track submission:
- submitTrack ack returns trackId + youtubeId; new blindtest:removeTrack
- lobby shows submitted tracks as cards (YouTube thumbnail + title) with delete
Verified e2e (3 players): add/remove, private mine flag, return-to-lobby reset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Default game type stays "mixed", but while fewer than 3 players are connected
the lobby renders the quiz config only (Quiz highlighted, Mixed/Blindtest
disabled) instead of showing blindtest settings to a lone host. It switches
back to the stored type automatically once 3 players are present — no manual
click needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- DJ is now the track's contributor (controls their own song); their identity
is sent only to them so "who added" stays non-trivial. The contributor
doesn't vote and is excluded from the eligible-voters count.
- Scoring: the contributor earns nothing except in who_added/mixed, where they
get a misdirection bonus (50) per player who guesses the wrong adder.
- Blindtest (and mixed) require >= 3 connected players: lobby disables the
options with a hint, and game:start rejects with NEED_THREE.
- Player card is now 16:9 and full width — the video banner shows at reveal;
DJ gets a seek bar (current/duration) to jump anywhere, plus play/pause/restart.
- Mixed game order is shuffled (no predictable quiz/blindtest alternation).
Verified e2e (3 players): guard rejects at 2, DJ id hidden from others,
misdirection scoring correct. 23 tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mixed mode (default):
- gameType is now mixed | quiz | blindtest, default "mixed"; the lobby
interleaves quiz + blindtest rounds so modes alternate
- lobby reworked: 3-way game-type switch, quiz count and/or blindtest config
+ track submission shown per selected type
Free-text quiz questions:
- quiz supports the `free` format (e.g. maths) alongside mcq/truefalse:
payload without choices, {text} vote, tolerant matching on acceptedAnswers
- shared QuizQuestionPayload.choices optional; reveal truth carries answer
- match util moved to game/match.ts (shared by quiz + blindtest)
- repo/seed include free + acceptedAnswers; in-code bank gains free questions
- client quiz view renders a text input for free questions
Mode-aware transitions:
- RoundTransition themed per mode (colors/label/emoji); announces the mode
on change (quiz <-> blindtest), lighter teaser within the same mode
- custom media buckets per mode: assets/transitions/{quiz,blindtest}/ + shared
- store tracks roundModeChanged
Verified e2e: mixed game alternates quiz/blindtest to completion; free-text
scoring covered by tests (22 pass).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- GameEndView: top-3 podium — 2nd left, champion center (taller), 3rd right,
with gold/silver/bronze pedestals, staggered rise-in (climax on the champion),
crown + pulsing gold glow kept on #1; ranks 4+ listed below
- bigger avatars where they read too small: lobby (size-7→11) and in-game
player cards (size-9→14, slightly wider cards)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Avatar component using DiceBear 9.x lorelei, seeded by the player name
(stable, recognizable across screens)
- shown in the lobby list, the in-game player cards (gold ring on leader),
and the final leaderboard (large on the winner, small on runners-up)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>