Files
joshuaandClaude Opus 5.5 b60c9db4f4 Phase 3: admin magic-link auth and event setup screens
- /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>
2026-10-03 13:47:36 +02:00

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

  1. The service role key is server-only. Never import it in a client component. Never prefix it NEXT_PUBLIC_.
  2. 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.
  3. 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.
  4. Realtime messages carry no data. Broadcast a { type: "refresh" } ping; clients refetch from the API. This keeps hidden/sanitised data rules in one place.
  5. 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.
  6. Tokens are unguessable (≥ 128 bits, hex). Validate shape with zod before hitting the DB.
  7. Mobile-first for judge pages (they're on phones). Scoreboard is 16:9 projector-first.
  8. Small commits per task. After each phase, stop and summarise what to test manually.

Code conventions

  • src/app routes, src/lib logic, src/components UI, src/lib/supabase/{server,admin,browser}.ts clients.
  • Server actions for admin mutations; route handlers (src/app/api/...) for public/judge.
  • Every mutation that affects scores/visibility calls notify() from src/lib/realtime.ts which 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.