- buildScoreboardPayload is the single place deciding what the public may
see: visible, frozen (snapshot scores, live current game), hidden (no
scores, alphabetical) and reveal (unrevealed teams carry no score/order).
- GET /api/public/scoreboard/[token] validates the token, then loads the
event with the service client in one parallel round trip.
- notify() pings sb/admin/game channels over Realtime's REST endpoint with
no data; useRefreshChannel refetches immediately on a ping, throttles
bursts, and falls back to a 10s poll, focus and reconnect.
- /s/[token]: FLIP rank animation, count-up totals, reduced motion,
fullscreen, cursor hide and a connection indicator.
- Admin setup actions now notify, so renames and reorders show up live.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- /login sends a Supabase magic link (admin emails only); /auth/confirm
completes sign-in; proxy.ts guards /admin and every server action
re-checks with requireAdmin(), since actions are plain POST endpoints.
- /admin lists, creates, duplicates and deletes events.
- /admin/events/[eventId] edits teams (colour, order) and games with
criteria, presets and notes. All input goes through zod schemas that
mirror the database constraints so errors read as plain sentences.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure functions in src/lib/scoring implementing docs/SCORING.md: cell values
(override > judge average), weighted raw totals, raw and placement points
with tie averaging, and competition-ranked standings. Coverage thresholds
are enforced at 100% for the module. Also silences the hydration warning
caused by browser extensions modifying <html>.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>