- /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>
3.2 KiB
CLAUDE.md — Game Night Live
You are building a live scoring web app for a church youth group's game nights.
Read docs/ before writing code. Docs are the source of truth; if code and docs disagree, ask.
Stack (do not swap without asking)
- Next.js (App Router, latest stable) + TypeScript (strict)
- Tailwind CSS
- Supabase: Postgres, Auth (admin only, email magic link), Realtime (Broadcast)
- zod for all input validation
- Vitest for unit tests (scoring logic MUST be tested)
- npm as package manager
- Deploy target: Vercel
Verify current Next.js and Supabase APIs against their official docs before using them;
don't rely on memory for SDK method names (esp. @supabase/ssr and Realtime broadcast from the server).
Non-negotiable rules
- The service role key is server-only. Never import it in a client component. Never prefix it
NEXT_PUBLIC_. - Anon users get zero table access. RLS is on for every table. Scoreboard and judge pages read/write ONLY through Next.js route handlers that validate the token and use the service-role client.
- Hiding the scoreboard is enforced on the server. When hidden, the scoreboard API must not return scores at all. Never hide with CSS only — someone will open devtools.
- Realtime messages carry no data. Broadcast a
{ type: "refresh" }ping; clients refetch from the API. This keeps hidden/sanitised data rules in one place. - One scoring engine. All score math lives in
src/lib/scoring/as pure functions with tests. Admin view, scoreboard API and judge view all call it. No score math in components or SQL views. - Tokens are unguessable (≥ 128 bits, hex). Validate shape with zod before hitting the DB.
- Mobile-first for judge pages (they're on phones). Scoreboard is 16:9 projector-first.
- Small commits per task. After each phase, stop and summarise what to test manually.
Code conventions
src/approutes,src/liblogic,src/componentsUI,src/lib/supabase/{server,admin,browser}.tsclients.- Server actions for admin mutations; route handlers (
src/app/api/...) for public/judge. - Every mutation that affects scores/visibility calls
notify()fromsrc/lib/realtime.tswhich pings the relevant channels (see ARCHITECTURE.md). - Use DB types generated by
supabase gen types typescript. - Explain why in PR-style summaries, not just what changed.
Commands
npm run dev/npm run build/npm run test/npm run lint- Migrations live in
supabase/migrations/. Apply via Supabase CLI or paste into SQL editor.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ (resolved from this file's directory; in monorepos the next package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by next dev — verify at node_modules/next/dist/server/lib/generate-agent-files.js. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.