Track. Honk. Tip. β an Uber-style ride tracker for one very specific driver: Dad.
DadCab is a private family PWA. Kids request a ride, watch Dad's cab move on a live map, get a push notification when he's close, and rate the ride (and the driver) when it's over. Dad gets a dispatch view, ride queue, and β because no family app is complete without it β a live panel showing what the whole thing costs to run.
Built for the O'Brien family. Live at dadcab.fly.dev (invite-only β the URL token is the credential).
- Ride requests β kids pick a saved destination (school, practice, a friend's house) and request a pickup. Requests de-dupe so mashing the button doesn't summon five dads.
- Live tracking β Dad's phone streams location while a ride is active; the kid's view shows the cab moving on a map with ETA.
- Ride lifecycle β request β accept β en route β picked up β arrived, with push notifications at every step.
- Ratings, both directions β riders rate the driver and the driver rates the riders, across fun custom categories (snack provisioning, aux-cord generosity, on-time departure...). Stats pages keep the leaderboard honest.
- Messages & moods β lightweight in-app messages and mood check-ins between driver and riders.
- Ride history β every completed trip, browsable.
- Cost panel β the admin view queries the Fly.io billing/machines APIs to show what the app actually costs to host (spoiler: nearly nothing).
- Backend: FastAPI (~1,200 lines total) + SQLite. No ORM, no framework magic β
db.pyis plain SQL. - Frontend: vanilla JS/HTML PWA β separate installable views for kids (
/k/β¦), Dad (/d/β¦), history, and admin. Per-role web manifests so "Add to Home Screen" opens the right page. - Push: Web Push (VAPID) via
pywebpush; expired subscriptions self-clean on 404/410. - Auth: a secret room token in the URL is the invite; a PIN + signed HttpOnly cookie keeps sessions. Secrets come from env vars (Fly secrets in prod) β nothing sensitive in the repo.
- Hosting: a single small Fly.io machine with a volume for SQLite.
Dockerfile+fly.tomlincluded.
uv sync
uv run uvicorn app.main:app --reloadOn first run a dev room token is generated into data/secret.txt. Open http://localhost:8000/k/<token> for the kid view, /d/<token> for the driver view.
Deploy: fly launch, then set secrets (DADCAB_SECRET, DADCAB_COOKIE_SECRET, VAPID_PUBLIC, VAPID_PRIVATE, VAPID_EMAIL).
Because "I'm five minutes away" has meant anywhere from 5 to 40 minutes for as long as cars have existed, and the kids deserved better telemetry.