A shop for Quiz App is a Next.js quiz game with solo play and real-time multiplayer rooms. Questions are generated by OpenAI, while Supabase provides anonymous player identities, room persistence, authoritative scoring, and live room updates. The production site is www.ashopforquiz.com.
Players can choose a curated or custom topic, difficulty, and 10, 15, or 20 questions. Multiplayer rooms support 2–10 players, synchronized rounds, live standings, reconnects, host recovery, rematches, and shared winners.
┌─────────────────┐
│ OpenAI │
│ quiz generation │
└────────▲────────┘
│ server only
┌─────────────────┐ ┌─────────┴─────────┐
│ │ HTTPS │ │
│ Next.js client ├─────────►│ Next.js App Router│
│ │◄─────────┤ pages + API routes│
└────────┬────────┘ snapshots└─────────┬─────────┘
│ │ authenticated RPCs
│ private Realtime │ and room reads
│ invalidation events ▼
│ ┌─────────────────────┐
└──────────────────►│ Supabase │
│ Anonymous Auth │
│ Postgres + RLS │
│ Realtime Broadcast │
└─────────────────────┘
The browser requests a quiz from /api/openai. The server validates the topic and settings, asks GPT-5.6 Terra for a structured question set with medium reasoning, and checks the result for repeated questions and duplicate options. Correct-answer positions are balanced before the public quiz data is returned. A failed quality check triggers one targeted regeneration. Solo progress, timers, answers, and scoring remain in the browser.
The browser signs in with Supabase Anonymous Auth and uses the Next.js game API routes to create, join, and play in a room. API routes verify the player and delegate state changes to transactional Postgres functions.
Postgres is authoritative for room membership, phase deadlines, accepted answers, scoring, rankings, host transfer, and rematches. Realtime Broadcast events only tell clients that room data changed; clients then fetch a fresh authoritative snapshot.
The match state machine is:
lobby → generating → countdown → question → reveal
▲ │
└───────────┘
... → finished
- Next.js App Router, React, and TypeScript
- Material UI with Tailwind global utilities
- OpenAI Responses API with GPT-5.6 Terra, low reasoning, and structured outputs
- Supabase Anonymous Auth, Postgres, RLS, database functions, Realtime Broadcast, and Cron
- Vitest for unit and Supabase integration tests
You need:
- Node.js and npm
- A Supabase project
- An OpenAI API key
- The Supabase CLI if you want to apply migrations from the terminal
npm installIn the Supabase dashboard, enable Authentication → Providers → Anonymous Sign-Ins.
Apply all SQL migrations from supabase/migrations in timestamp order. If the Supabase CLI is installed and this repository is linked to your project, run:
npx supabase db pushThe migrations install the multiplayer schema, RLS policies, private Realtime authorization, transactional game functions, and the scheduled cleanup job.
Create .env.local in the project root:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
NEXT_PUBLIC_SITE_URL=https://www.ashopforquiz.com
SUPABASE_SECRET_KEY=sb_secret_...
OPENAI_API_KEY=sk-...| Variable | Used by | Purpose |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Browser and server | Supabase project URL |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Browser and server | Safe public key used with RLS and anonymous Auth |
NEXT_PUBLIC_SITE_URL |
Browser and server | Canonical public URL used for metadata and search files |
SUPABASE_SECRET_KEY |
Server only | Privileged room functions and administrative operations |
OPENAI_API_KEY |
Server only | Quiz generation |
Legacy Supabase service-role JWTs can be supplied as SUPABASE_SERVICE_ROLE_KEY instead of SUPABASE_SECRET_KEY. Never add a NEXT_PUBLIC_ prefix to either server-only key, and never commit .env.local.
npm run devOpen http://localhost:3000.
Solo mode is ready when the app can generate a quiz. To verify multiplayer, create a room and open its shared link in a private/incognito window so the second browser receives a separate anonymous identity.
npm test # deterministic unit tests; does not call OpenAI
npm run test:db # live integration tests against the configured Supabase project
npm run lint
npm run typecheck
npm run buildThe database suite creates and removes temporary rooms and anonymous users. Run it only against a development or staging Supabase project.
| Path | Responsibility |
|---|---|
app/page.tsx |
Mode selection and solo/multiplayer setup |
app/question |
Solo quiz lifecycle and results |
app/game/[code] |
Multiplayer lobby, match synchronization, reconnect, and results |
app/api/openai |
Validated, server-side OpenAI quiz generation |
app/api/games |
Authenticated multiplayer commands and snapshots |
app/utils/multiplayer |
Shared validation, scoring, timing, ranking, and public types |
lib/games/server.ts |
Server orchestration around Supabase database functions |
lib/supabase |
Browser, server, admin, and middleware Supabase clients |
supabase/migrations |
Database schema, RLS, functions, Realtime, and cleanup lifecycle |
supabase/tests |
Live database authorization and match lifecycle tests |
Full browser automation remains planned for the Playwright checkpoint.