A JavaScript app where users visit 5 locations in order.
- Each location has a fixed letter configured in admin.
- Reaching the active location awards that location's letter.
- After Confirm letter and next location, the next target unlocks.
- Optional map tools (Google Maps/OpenStreetMap) help navigation.
- Anti-cheat checks filter low-quality GPS and unrealistic jumps.
- Node.js 18+
- Supabase project + Supabase CLI (
npm install -g supabase) - Browser/device with Geolocation API
- Create a Supabase project.
- Open Supabase SQL Editor and run
supabase/schema.sql. - Before opening
/admin.html, bootstrap your first admin allowlist row viasupabase/admin-bootstrap.sql(seesupabase/ADMIN_ROLLOUT_NOTES.md). - Enable Email/Password auth in Supabase (for admin login).
- (Optional) Enable GitHub auth provider if you want Sign in with GitHub on admin.
- Copy
.env.exampleto.env.localand fill in your values (find them in Supabase → Settings → API):
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-keyThe game uses Supabase Edge Functions for gameplay and payment:
get-game— returns safe game metadata + first location only.get-route-start— returns first location of a route.confirm-arrival— returns the letter + next location when no question is required.check-answer— validates answer server-side and returns letter + next location only if correct.create-payment— creates a payment session (mock or real Tikkie).check-payment— checks payment status by request token or payment token.tikkie-webhook— confirms payment (called by mock page or real Tikkie webhook).mark-played— marks a paid session as consumed after finishing.record-score-event— stores score events and updates totals.get-scoreboard— returns top 3 overall plus up to 3 runs for the current player.set-score-display-name— updates scoreboard display name for a player's runs.
Shared edge helpers:
supabase/functions/_shared/paymentVerification.ts— shared paid-token verification used by gameplay endpoints.
Leaderboard rules:
- Correct answer points: 10 (1st), 5 (2nd), 3 (3rd), 2 (4th), 1 (5th+).
- Answering within 60 seconds adds the remaining whole seconds as a bonus.
- Rankings are sorted by score descending, then total answer time ascending.
- The separate rankings page shows the top 3 overall plus up to 3 of the current player's own runs.
- Log in to the Supabase CLI and link your project:
supabase login
supabase link --project-ref your-project-refFind your project ref in Supabase → Settings → General.
- Set the service role key as a secret (find it in Supabase → Settings → API →
service_role):
supabase secrets set SERVICE_ROLE_KEY=your-service-role-key- Deploy functions:
supabase functions deploy get-game
supabase functions deploy get-route-start
supabase functions deploy confirm-arrival
supabase functions deploy check-answer
supabase functions deploy create-payment
supabase functions deploy check-payment
supabase functions deploy tikkie-webhook
supabase functions deploy mark-played
supabase functions deploy record-score-event
supabase functions deploy get-scoreboard
supabase functions deploy set-score-display-nameRedeploy all functions in one command:
npm run deploy:functionsPreview which functions would deploy without executing:
npm run deploy:functions:dryBy default, payment flow can run in mock mode. To use the real ABN AMRO Tikkie API, do this:
- Create/activate a Tikkie app in ABN AMRO Developer Portal and collect:
TIKKIE_API_KEYTIKKIE_APP_TOKEN
- Set Supabase Edge Function secrets:
supabase secrets set TIKKIE_MOCK=false
supabase secrets set TIKKIE_API_KEY=your-tikkie-api-key
supabase secrets set TIKKIE_APP_TOKEN=your-tikkie-app-token
supabase secrets set TIKKIE_BASE_URL=https://api.abnamro.com/v2/tikkie- Register your webhook URL in ABN AMRO/Tikkie app settings:
https://<your-project-ref>.supabase.co/functions/v1/tikkie-webhook
- Redeploy payment-related functions:
supabase functions deploy create-payment
supabase functions deploy check-payment
supabase functions deploy tikkie-webhook
supabase functions deploy mark-played- (Optional hardening) enable strict paid-token checks in gameplay functions:
supabase secrets set STRICT_PAYMENT_VERIFICATION=true
supabase functions deploy get-route-start
supabase functions deploy confirm-arrival
supabase functions deploy check-answerFor ABN AMRO sandbox testing, use:
supabase secrets set TIKKIE_BASE_URL=https://api-sandbox.abnamro.com/v2/tikkieKeep TIKKIE_MOCK=false when testing real (sandbox) API calls.
npm install
npm run dev- Game:
/ - Rankings:
/rankings.html?slug=<game-slug> - Admin:
/admin.html - Language switch: both pages support
ENandNLfrom the top selector.
- Sign in (email/password or GitHub if configured).
- Edit 5 locations: name, letter, latitude, longitude.
- Hint fields per location:
description: shown on the target card during the location phase.question_hint: shown in the question hint panel during the question phase.
- Or click Pick from map and click on map to fill coordinates.
- Click Save Settings to save shared route config to Supabase.
- Game page
/loads the shared route (players do not need sign-in).
Run these commands from the project root:
git init
git add .
git commit -m "Initial Letter Quest app"
git branch -M main
git remote add origin https://github.com/<your-username>/<your-repo>.git
git push -u origin mainIf origin already exists:
git remote set-url origin https://github.com/<your-username>/<your-repo>.git
git push -u origin main- Go to
https://vercel.com/new - Import your GitHub repo.
- Add project env vars in Vercel settings:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
- Deploy.
Edge Functions are deployed separately via the Supabase CLI (see above) and are independent of Vercel.
After deploy, open your HTTPS URL on phone and add to home screen.
- Push your project to GitHub.
- Open Netlify -> Add new site -> Import an existing project.
- Choose GitHub and select your repo.
- Use these build settings:
- Build command:
npm run build - Publish directory:
dist
- Build command:
- Add environment variables in Netlify:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
- Click Deploy site.
npm install
npm run buildThen in Netlify, open Sites and drag the local dist folder into the deploy area.
- Open
https://<your-site>.netlify.app/(game page). - Open
https://<your-site>.netlify.app/admin.html(admin page). - Sign in on admin and save one test location change.
- Reload
/and confirm the new shared config is visible.
- If you forgot env vars on first deploy, add them in Site configuration -> Environment variables and trigger a redeploy.
- Keep
.envout of Git; only.env.exampleshould be committed. - Your app uses
admin.htmlas a separate page, so no SPA redirect rule is required for this setup.
npm run test:logicnpm run lintAuto-fix lint issues (including missing semicolons):
npm run lint:fixnpm run build
npm run previewAdjust in src/main.js:
MIN_GPS_ACCURACY_METERSLETTER_COOLDOWN_MSMAX_SPEED_METERS_PER_SECONDMAX_JUMP_DISTANCE_METERS
- Android Chrome: Add to Home screen
- iPhone Safari: Share -> Add to Home Screen
- Geolocation needs HTTPS in production (localhost is fine for local dev)