Skip to content

Repository files navigation

🏀 Basketball Shot Tracker

A live, classroom-wide basketball data app for an after-school program that teaches data science to kids. A teacher starts a session, students join with a code from any device, and the whole class plays a tabletop mini-basketball game through two structured rounds. Every shot gets tracked by court zone, then each kid sees their own color-coded heat map and stats, turning a game they just played into data they can actually read.

🎬 Demo: https://basketball-shot-tracker-21c0e.web.app/

Basketball Shot Tracker demo

Prefer motion? There's a full video walkthrough too.

flowchart TD
    A["🟢 LOBBY<br/>students join with a 6-char code + nickname"] -->|"Teacher starts round 1"| B["🏀 SOLO ACTIVE<br/>tap a zone, record made or missed (x20)"]
    B -->|"Teacher ends round, shows review"| C["📊 SOLO REVIEW<br/>personal heat map + stats"]
    C -->|"Teacher forms teams"| D["🤝 TEAM STRATEGY<br/>compare heat maps, plan shots"]
    D -->|"Teacher starts allocation"| E["🎯 ALLOCATION<br/>split team shots per player"]
    E -->|"Teacher starts sabotage"| F["💣 SABOTAGE<br/>block rival hot zones"]
    F -->|"Teacher starts team shooting"| G["🏀 TEAM ACTIVE<br/>shoot as a team, blocked zones enforced"]
    G -->|"Teacher shows results"| H["🏆 TEAM REVIEW<br/>team heat map + leaderboard"]
Loading

Every screen advances in lock-step the moment the teacher moves the session forward: no refresh, no re-join.


✨ Features

  • Live multi-device sessions : Students join with a 6-character code, no login.
  • Teacher-driven state machine : One tap advances every connected screen in real time.
  • Tap-a-zone : Shot input on a 6-zone half-court, with undo.
  • Solo round : Individual shot tracking with a per-zone scoring system.
  • Team round : Auto-pairing, shot allocation, and a "sabotage" mechanic that blocks a rival team's zone.
  • Heat Maps : Personal, team, and class-wide heat maps color-coded by make/miss percentage.
  • Leaderboard : Shows top 5 players and teams.
  • Random Name Generator : Kid-friendly nickname generator (e.g. SpeedyHooper).
  • Resilient sessions : Teacher heartbeat, disconnect detection, and idle timeouts auto-recover stranded students.
  • Practice Mode : Offline single-device play with no Firebase required.

🧰 Tech stack

Stage Tooling
Language TypeScript
UI React 18
Build / dev server Vite
Database & real-time sync Firebase Firestore (serverless, onSnapshot listeners)
Hosting Firebase Hosting
Export html2canvas + jsPDF
Unit / component tests Vitest + Testing Library
Integration tests Firebase Emulator
End-to-end tests Playwright

🛠️ How I built it (the process)

This started as a way to replace the clunky Google Forms + Sheets workflow the program used to collect shot data; but the real goal was bigger: give low-income kids a fun, visual way to understand their own data. A spreadsheet doesn't teach a 12-year-old anything; a heat map of their own shooting does. So the whole design leans into the game itself, then quietly turns it into a data-science lesson at the end.

I wrote a detailed PRD first and built around a single session state machine. Every screen is just a function of the current session status, which the teacher controls. The frontend is intentionally backend-free: Firestore's onSnapshot listeners (wrapped in a useSession hook) push every state change to every device, so the teacher tapping "Start Team Shooting" instantly moves the whole class forward. The hardest parts were all about liveness: keeping many student and teacher screens perfectly in sync, handling the messy reality of a teacher closing their laptop mid-session (heartbeats, beforeunload, timeouts, and idle detection so kids never get stranded), and designing a two-round game (zone scoring, team shot allocation, and a sabotage mechanic) fun enough to keep kids engaged while still producing clean data.

Guiding principle: simple and playful for the kid in front of the screen, even when the sync logic behind it isn't.


📚 What I learned

  • Modeling a real-time multi-user app around Firestore onSnapshot listeners and a fully serverless (no-backend) architecture.
  • Designing a simple, playful, Kahoot-style UI that actually works for 10–14 year olds.
  • Testing concurrency for real Firestore emulator tests, multi-user simulations, Playwright E2E, and a bot script that hammers a session with 25 fake students.
  • Writing Firestore security rules to validate every write and protect data integrity without a traditional backend.

🚀 How it could be improved

  • No authentication : Anyone with a code can join. Fine for a supervised classroom, but real auth (or per-class teacher accounts) would harden it for wider use.
  • Open Firestore reads : Rules currently allow public reads on sessions. Scoping reads to participants would tighten privacy.
  • No session history / data export per student : Results live only for the session. Persisting longitudinal data would let kids track progress over weeks.
  • Single teacher per session :No co-teacher or multi-class admin view yet. An admin panel is the natural next step as the program scales.
  • Fixed shot limits and zones : Scoring and zone layout are hard-coded; making them teacher-configurable would support different game variants.

▶️ How to run the project

Prerequisites

Quick start

git clone https://github.com/pieroevcc/Basketball-Data-Collection-Web-App.git
cd Basketball-Data-Collection-Web-App
npm install
npm run dev

Open http://localhost:5173. Without Firebase configured, the app still runs in Practice Mode (offline, single device).

🔧 Firebase setup (for live sessions)

Create a .env file in the project root (see .env.example) with your Firebase web-app config:

VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id
VITE_FIREBASE_MEASUREMENT_ID=your_measurement_id   # optional

These values come from your Firebase Console → Project Settings → Your apps. The app reads them at startup; if the core keys are missing it silently falls back to Practice Mode.

🚢 Deploy to Firebase Hosting
npm install -g firebase-tools
firebase login
npm run build
firebase deploy

Firestore rules and indexes ship from firestore.rules and firestore.indexes.json.

🧪 Running the tests
npm test                  # unit + component tests (Vitest)
npm run test:emulator:ci  # integration tests against the Firestore emulator
npm run test:e2e          # Playwright end-to-end tests
npm run test:all          # everything

The emulator and bot scripts need the Firebase CLI installed.


Built for a non-profit after-school program teaching data science through a tabletop basketball game.

About

Real-time multiplayer web app where kids play a tabletop basketball game and turn their shots into heat maps and stats — teaching data science by playing. React + TypeScript + Firebase.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages