Phuzzle uses Supabase for leaderboards, stats, achievements, profiles, and co-op. The app runs without it, but those features need a configured project.
| Feature | Description |
|---|---|
| Leaderboards | Daily, weekly, all-time; streaks; best times per grid |
| Player stats | Completions, play time, streaks |
| Achievements | Badges (first puzzle, streaks, speed runs, etc.) |
| Profile | Display name, anonymous mode (raccoon names on leaderboards) |
| Co-op | Play menu -> Play -> Co-op real-time sessions |
| Daily comments | Reactions and comments on daily puzzle; report for moderation |
- Go to supabase.com and sign in.
- New Project → organization, name, password, region.
- Wait for provisioning.
Create or update .env.local:
VITE_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_public_key- Where: Dashboard → Settings → API. Project URL →
VITE_SUPABASE_URL; anon public key →VITE_SUPABASE_ANON_KEY. - Note: Only vars starting with
VITE_are exposed. Restart the dev server after changing env. In production (e.g. Vercel), add the same vars and redeploy.
- Dashboard → Authentication → Providers.
- Enable Anonymous sign-ins.
- Save.
Anonymous users can have stats and leaderboard entries without signing up.
Two migration files (both idempotent):
| File | Contents |
|---|---|
supabase/migrations/20260225120000_tables.sql |
Tables, indexes, Realtime, server-time RPC |
supabase/migrations/20260225120001_rls.sql |
RLS policies |
Option A — CLI
npx supabase db pushOption B — Dashboard
- SQL Editor → New query.
- Run
20260225120000_tables.sql, then20260225120001_rls.sql.
Run tables first, then RLS.
Required for co-op and live completion counts.
Option A — Dashboard
Database → Publications → supabase_realtime → add tables puzzle_sessions, completions.
Option B — SQL
alter publication supabase_realtime add table public.puzzle_sessions;
alter publication supabase_realtime add table public.completions;The tables migration sets REPLICA IDENTITY FULL on puzzle_sessions for Realtime.
npm run devand open the app.- Open Leaderboard from the Play menu, or go directly to
/stats. - Complete a puzzle and confirm stats record.
If you see “Connect Supabase to track your stats…”:
- Env vars set and dev server restarted
- Migrations ran without errors
- Anonymous auth enabled
| Table | Purpose |
|---|---|
player_stats |
Per-user: completions, play time, streaks |
completions |
Each completion; used for leaderboards |
player_profiles |
Display name, leaderboard visibility |
user_achievements |
Unlocked achievements per user |
puzzle_sessions |
Co-op session state |
RLS is on for all tables. Policies: users manage their own stats/profiles/achievements; completions readable by all (leaderboards); puzzle_sessions allow create/read/update for participants.
If leaderboards stay empty after completing puzzles, check that RLS migrations ran.
Anonymous sign-in fails
- Confirm Anonymous auth is enabled and not restricted.
Leaderboards empty
- Complete at least one puzzle.
- Confirm migrations and that the client has an anonymous session.
Co-op not syncing / WebSocket closes
- Realtime:
puzzle_sessionsandcompletionsinsupabase_realtime. - Env vars set in Vercel and app redeployed.
- Try incognito (extensions can block WebSockets).
Env vars not loading
- Names must start with
VITE_. - Restart dev server.
- Check for
.envsyntax errors.
- Supabase configured (env, migrations, anonymous auth, Realtime).
- Start any puzzle -> Play menu -> Play -> Co-op.
- Copy or share the URL; open in another tab or device.
- Move a piece in one tab; it should appear in the other.
Completion share (after finishing a puzzle) does not need Supabase.
src/app/supabase/client.ts— client and configsrc/app/supabase/auth.ts— anonymous auth helperssupabase/migrations/— tables and RLSsupabase/README.md— short reference