A lightweight mental-math balloon game for kids. Timed rounds, rising balloons, telephone-style dialpad input, per-kid accounts with persistent stats. Runs as a PWA so kids can "Add to Home Screen" on Android and launch fullscreen.
- React + Vite + TypeScript
vite-plugin-pwafor the manifest + service worker- Supabase for auth and the
statstable
- Install deps:
npm install
- Create a Supabase project at https://supabase.com and grab the project URL + anon key.
- Copy the env template and fill it in:
cp .env.template .env # edit .env and set VITE_SUPABASE_URL + VITE_SUPABASE_ANON_KEY - Apply the database schema. In the Supabase dashboard → SQL Editor, paste
and run the contents of
supabase/migrations/0001_init.sql. This creates thestatstable, row-level security policy, and the auth-user trigger that auto-creates a stats row for each new sign-up. - (Optional) Turn off "Confirm email" in Supabase → Authentication → Providers → Email → "Confirm email" if you want kids to sign up and play without clicking a confirmation link. Alternatively, keep it on and have them click the link on their first sign-up.
npm run devOpen http://localhost:5173 in Chrome and use device emulation (DevTools → Toggle Device Toolbar → iPhone 12 Pro or similar) for a phone-shaped preview.
npm run build
npm run preview # serves the production build locallyAny static host works. For Netlify or Vercel:
- Connect this repo.
- Build command:
npm run build - Publish dir:
dist - Env vars:
VITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEY
After deploy, on an Android phone:
- Open the URL in Chrome.
- Chrome menu → Add to Home Screen.
- Launch from the home screen — it opens full-screen in portrait.
- 60-second rounds. Balloons spawn at the bottom and rise toward spikes.
- Each balloon carries a math question. Answer via the dialpad at the bottom — auto-matches any visible balloon, no Enter key.
- Saved balloon → XP and streak + 1. Balloon hits the spikes → streak resets to 0.
- XP per balloon =
10 × difficultyMult × speedMult- difficulty: easy 1.0 / medium 1.5 / hard 2.0
- speed: chill 1.0 / normal 1.5 / fast 2.0
- Difficulty controls number ranges and concurrent balloons (3 / 4 / 5).
- Speed controls rise duration (15s / 10s / 6s) and the XP multiplier.
- Best round — highest XP scored in a single round.
- Total XP — cumulative across all rounds.
- Correct streak — lifetime streak that only resets when a balloon pops.
npm run dev— dev servernpm run build— type-check + Vite production buildnpm run preview— servedist/npm run typecheck— TypeScript check onlynpm run check:questions— sanity-check the question generator rangesnode scripts/make-icons.mjs— regenerate placeholder PWA icons
- Ranges:
src/game/questions.ts(CFGobject) - Pacing / XP:
src/game/config.ts - Styling:
src/styles/index.css - Icons: replace
public/icons/icon-192.png+icon-512.pngwith real artwork