CheckBall is a basketball training app built on one bet: the camera is already pointed at the rim, so counting your makes shouldn't be your job. You record a shooting session, and Google's Gemini watches the footage, counts the shots taken, made, and missed, and hands them back as clean numbers — a stats card, a shots-over-time chart, and a heatmap of where you were hot and where you were cold.
The interesting part is how the model returns data. Instead of asking it "how did they shoot?" and parsing a paragraph, CheckBall gives Gemini a typed function to fill in — shotsTaken, shotsMade, shotsMissed — so the output arrives already structured, not scraped out of prose. It's a two-model relay: a vision model does the hard work of actually watching the video, then a fast model shapes what it saw into integers.
That "watch a video" step is slow — one to five minutes — and a callable cloud function times out at sixty seconds. So the constraint chose the architecture. One function enqueues the job and returns immediately; a Cloud Tasks queue (named barbequeue) holds it; a second function does the slow analysis on its own clock and writes the results to a status document; and the app finds out by listening to that document instead of waiting on the wire. The timeout wasn't a bug to fix — it was the thing that decided the whole shape.
I built the whole thing solo: a four-platform Flutter client, the Firebase backend, the data model, the async pipeline, and the AI integration. Practice mode and the stats dashboard are shipped and real; Versus — competitive modes like 1v1 and H-O-R-S-E — is scaffolded against a multiplayer-ready schema and waiting on the next build. It's a prototype, not a public launch, but the engineering that matters is done.