# 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).