Files
game-scoreboard/docs/PRD.md
T
joshuaandClaude Opus 5.5 c89a82295b Phase 0: scaffold Next.js, Tailwind tokens, Supabase clients, env validation
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>
2026-10-03 12:27:11 +02:00

102 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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) or `number` (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) and `judge_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 `live` and 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.
- 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: `N` next game, `P` prev game, `H` cycle 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: `participants` per team).
- Multiple admins / co-hosts (stretch).
- Timers/buzzers (stretch).