Offline-first puzzle game - a demonstration of a modern web stack featuring a custom-built sleek UI design system. Built with React (Vite), Hono (Vercel API), and Supabase.
- Node: 20+
- pnpm:
npm install -g pnpm
pnpm install
pnpm build# Web app (Vite)
pnpm dev:web
# API (Hono)
pnpm dev:apiOr both in parallel: pnpm dev
apps/web– React (Vite) frontendapps/api– Hono API (Vercel serverless)packages/shared– Zod schemas, events, API contracts
Copy .env.example to .env.local and fill in all values. Both the API and the web app (Vite) read from .env.local at the repo root.
- DATABASE_URL: Use the pooler URI from Supabase (Database → Connect → Connection pooling → Transaction or Session), not Direct. Direct (
db.xxx.supabase.co) can causegetaddrinfo ENOTFOUND; pooler (xxx.pooler.supabase.com) works. - VITE_*: Same Supabase URL/key as above. For local dev set
VITE_API_URL=http://localhost:3000and run the API withpnpm dev:apiso the web app at localhost:5173 talks to your local API. (Using the Vercel API URL from localhost causes CORS and 404 unless the API is deployed and allows your origin.)
Vercel: Do not run “Pull environment variables” when linking (vercel link) – it overwrites .env.local. Add the same variables in the Vercel project (Settings → Environment Variables) and set DATABASE_URL to the pooler URI there too. For production, set VITE_API_URL to your deployed API URL.
Run the initial migration in Supabase SQL Editor (Dashboard → SQL Editor → New query). Paste and run the contents of apps/api/migrations/001_initial.sql.
-
Apply the migration in Supabase (see above) if you haven’t already.
-
Install and build
pnpm install pnpm build
-
Start the API
pnpm dev:api
API runs at
http://localhost:3000. -
Test unauthenticated endpoints
curl http://localhost:3000/health # → {"ok":true} curl http://localhost:3000/leaderboards/level_1 # → {"levelId":"level_1","entries":[]}
-
Test sync (requires a Supabase access token)
- Create a user in Supabase: Dashboard → Authentication → Users → Add user (email + password).
- Get an access token (loads
SUPABASE_URLandSUPABASE_PUBLISHABLE_KEYfrom.env.local):Copy the printed token, or pipe to clipboard:./scripts/get-auth-token.sh your@email.com yourpassword
./scripts/get-auth-token.sh your@email.com yourpassword | pbcopy(macOS). - Call sync (replace
TOKENwith the value from above):Expected:curl -X POST http://localhost:3000/sync \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"events":[{"type":"LEVEL_COMPLETED","payload":{"levelId":"level_1","moves":10,"timeMs":5000}}]}'
{"acceptedCount":1,"rejectedCount":0}. Then:You should see one entry.curl http://localhost:3000/leaderboards/level_1
-
Web app
pnpm dev:web→http://localhost:5173. Sign in, play levels (Home → Play), sync, view leaderboard.
CI runs on every push and pull request to main (see .github/workflows/ci.yml):
- Install –
pnpm install --frozen-lockfile - Build –
pnpm run build(shared, api, web) - Lint –
pnpm run lint
In-flight runs for the same branch are cancelled when a new run is triggered.
→ Full step-by-step: docs/DEPLOY.md (connect repo, env vars, migrations, verify).
Connect this repo to Vercel so that pushes to main (and optionally PRs) trigger automatic deploys. Use two Vercel projects (one for the API, one for the web app), both pointing at this repo.
- In Vercel: Add New → Project → Import this GitHub repo (or connect GitHub first in Account Settings).
- Root Directory:
apps/api. - Build & Development: Leave Build Command empty (or use the default). Set Install Command to:
cd ../.. && pnpm install. (Or in dashboard: Settings → General → Install Command.) - Environment variables: Add the same vars as in
.env.example(noVITE_*). Use the poolerDATABASE_URL. Do not pull from a linked env file if it would overwrite. - Deploy. Note the API URL (e.g.
https://your-api.vercel.app).
- Add New → Project → Import the same repo again (create a second project).
- Root Directory:
apps/web. - Build & Development: Install Command:
cd ../.. && pnpm install. Build Command:cd ../.. && pnpm run build --filter web. Output Directory:dist. - Environment variables: Add
VITE_SUPABASE_URL,VITE_SUPABASE_PUBLISHABLE_KEY, and VITE_API_URL = your deployed API URL from the API project. - Deploy. The web app will call the API; CORS allows
*.vercel.apporigins.
- In each Vercel project, Settings → Git confirms the connected repo and branch (e.g. Production Branch:
main). Pushes tomaindeploy to production; PRs get preview URLs if enabled. - Run the DB migrations in Supabase if not already done.
- Create a user in Supabase Auth and use the web app to sign in, play, sync, and view leaderboards.