Next.js 16 App Router with strict TypeScript, Tailwind 4 theme tokens from docs/UI.md, Vitest, and the three Supabase clients. Env vars are validated with zod in next.config.ts so dev and build fail fast with a readable error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.0 KiB
6.0 KiB
PRD — Game Night Live
1. Goal
Run a youth game night (e.g. "Worship Game Night") from one admin tab while a projector tab shows a live scoreboard, and judges score from their phones via links. Versatile enough for any game format.
2. Roles
| Role | Access | How they get in |
|---|---|---|
| Admin | Everything | Logs in (magic link). Email must be in ADMIN_EMAILS. |
| Scoreboard viewer | Read-only scoreboard for ONE event | Public link /s/{scoreboardToken} |
| Judge | Score ONE game | Personal link /j/{judgeToken} OR open game link /jo/{openToken} (enters name first) |
3. Core concepts
- Event — one game night. Has teams, games, one scoreboard link, visibility state.
- Team — name + colour. Belongs to an event.
- Game — one activity. Ordered. Has a scoring mode:
judged— judges submit scores via links; admin can see progress & override.direct— admin enters scores directly.
- Criterion ("block") — one thing being scored in a game. A game has 1..N criteria.
- e.g. Karaoke: Pitch, Energy, Lyrics accuracy, Stage presence, Crowd reaction (each 1–5).
- e.g. Guess the Lyric: one criterion "Correct answers" (number input, 0–20).
- Input type:
blocks(tap a number in a row of buttons) ornumber(free numeric input / +/- stepper). - Has min, max, step, weight, and a description (shown to whoever scores it).
- Points mode per game (how a game's result becomes leaderboard points):
raw— game points = criteria total × multiplier.placement— teams ranked by criteria total, then awarded placement points (default 10/7/5/3).
- Adjustment — bonus or penalty points with a reason, optionally tied to a game.
- Notes —
admin_notes(only admin sees) andjudge_notes(judges see) per game.
4. Features
4.1 Admin — Setup (/admin/events/[id])
- Create/edit/delete events; duplicate an event (copies teams, games, criteria — not scores).
- Teams: add, rename, recolour, reorder, delete.
- Games builder: add, reorder (drag or up/down), duplicate, delete.
- Title, description, scoring mode, points mode, multiplier, placement points.
- Criteria list: add/remove/reorder; label, description, input type, min/max/step, weight.
- Quick presets: "Karaoke (5 × 1–5)", "Single score (0–10)", "Points (number)", "Win/Lose (0–1)".
- Admin notes + judge notes (multiline).
- Judges (judged games only):
- Nominate judges by name → each gets a personal link (copy button + QR code).
- Toggle the open link on/off; anyone opening it types their name and becomes a judge.
- Revoke a judge (link stops working, their scores excluded).
- Share panel: scoreboard link + QR, all judge links per game.
4.2 Admin — Control room (/admin/events/[id]/live)
This is the screen used during the night. Must be fast and hard to mess up.
- Game switcher: Prev / Next buttons + list of all games with status (upcoming / live / done).
Setting a game as current marks it
liveand shows it on the scoreboard. - Current game panel:
- Scoring grid: rows = teams, columns = criteria, using the same block/number inputs.
- Direct mode: admin types/taps here. Autosaves.
- Judged mode: shows per-team average per criterion, a judge-progress matrix (✓ per judge per team), and per-judge breakdown on expand. Admin can override a cell (override wins over judge average; clearly marked; can be cleared).
- Spotlight: pick "now performing" team — judges see it highlighted.
- Lock judging toggle (judges become read-only).
- Mark game done.
- Admin notes visible.
- Scoring grid: rows = teams, columns = criteria, using the same block/number inputs.
- Bonus/penalty: per team quick buttons (+1, +5, +10, −5) and custom amount + reason. Recent adjustments list with undo.
- Scoreboard visibility: Visible / Frozen / Hidden (see 4.3). Big obvious toggle.
- "Open scoreboard" button (new tab) + "Reveal mode" button (see 4.3).
- Keyboard shortcuts:
Nnext game,Pprev game,Hcycle visibility,?help.
4.3 Scoreboard (/s/[token])
- Projector-first, 16:9, readable from the back of a hall.
- Shows: event name, current game title, team standings (rank, name, colour, total points), optionally per-game points columns for completed games.
- Updates live (< 1s) when admin changes anything. Rank changes animate.
- Visible — live totals.
- Frozen — shows totals as they were the moment it was frozen, with a subtle "scores frozen" note. Server stores the snapshot; live scores are not sent.
- Hidden — no scores sent at all. Shows team names (no order implied — alphabetical) and the current game, with a "scores are hidden" state.
- Reveal mode (admin-triggered): scoreboard reveals final standings last place → first, one team per admin click ("Reveal next"), then sets visibility to Visible.
- Auto-reconnects; also polls every 10s as a fallback. Shows a small offline dot if disconnected.
- Fullscreen button; hides cursor after inactivity.
4.4 Judge (/j/[token])
- Mobile-first. Shows game title, judge notes, and their own name.
- One card per team (spotlighted team pinned on top + highlighted).
- Each card: one block row per criterion (e.g. 1 2 3 4 5 big tap targets) with the criterion label + description; number criteria get a stepper.
- Autosaves on every tap; shows saved ✓ / saving / error per card.
- Judges see only their own scores — never other judges' or totals.
- If judging locked or game done: read-only with a message. If revoked: "This link is no longer active."
- Open link (
/jo/[token]): enter name → creates judge → redirects to personal link and stores it in localStorage so a refresh keeps them in.
5. Non-functional
- Live latency target < 1s on normal Wi-Fi.
- Works with ~10 teams, ~20 games, ~10 judges per game without lag.
- No data loss on refresh; all state server-side.
- Accessible: visible focus, sufficient contrast, tap targets ≥ 44px.
6. Out of scope (v1)
- Individual contestants within teams (stretch:
participantsper team). - Multiple admins / co-hosts (stretch).
- Timers/buzzers (stretch).