The problem
Why it needed building
Weekend box cricket and gully cricket are usually scored on paper, in a notes app, or not at all. Professional scoring apps are built for league cricket, with rules and setup screens that don’t fit a 6-over game between friends. The scorer is usually also playing, so recording a ball has to take one tap, mistakes have to be undoable, and a match must never be lost if the phone locks or the app is killed. Pocket Score started as an offline-only scorer in April 2026 and was rebuilt in v2 as an online, multi-user app.
My role
What I owned
- Product and design across 21 screens, including the "Midnight Studio" dark theme
- Ball-by-ball scoring engine built on flutter_bloc
- Supabase backend: Postgres schema, row-level security, RPC functions and triggers
- Live scores for followers with Supabase Realtime
- Player career stats and Batter, Bowler and Impact rankings
- CI with GitHub Actions: a release APK on every push to main
The approach
Key decisions
- 1
One bloc for every cricket rule
ScoreBloc models the full innings: striker, non-striker, bowler, partnership, extras, fall of wickets and the ball-by-ball log. Every rule is an event (RecordBall, ChangeBowler, RetirePlayer, StartSuperOverInnings…), so wides, no-balls with runs off the bat, free hits, run-outs, retirements and last man standing are handled in one place instead of in button handlers.
- 2
A guided match flow
Setup → team selection with captains → lineup → match rules → toss → openers → scoring → result. Max overs per bowler and power play overs are set after team selection, so they fit the actual squad size, and tied matches can go to a super over.
- 3
Live scores in real time
The scorer’s phone writes the live innings to Supabase after each ball. Everyone else follows on a live score screen that updates instantly through Supabase Realtime, and match lists show a game moving from live to completed without a refresh.
- 4
Groups and fair rankings
Players join a group with a 6-character invite code or a QR code. Each group has its own match history and leaderboard, and a ranking calculator combines strike rate, average, recent form, economy and fielding into Batter, Bowler and Impact scores, with a visible breakdown of each rating.
- 5
Rules in the database
Screens and blocs never build SQL; they call repositories, which call Postgres RPC functions for group joins, match and stats upserts and account deletion. Row-level security is on every table, so live scores can be public while users can only change their own data.
The product
Screens
Swipe to see more · tap a screen to open it full size
Challenges
The hard parts
Never losing a match
Match and score state serialise to JSON, and restore events rebuild the exact session from the saved live score after the app is killed or the battery dies.
Exact undo
Each state keeps a history of previous states, so undoing a ball restores the snapshot exactly instead of trying to recalculate backwards.
From offline to online
v1 kept everything on the device. The move to Supabase happened in stages (schema and security first, then RPCs, then realtime) while keeping the same bloc APIs, so the scoring screen never came to depend on the network.
Store account-deletion rules
Account deletion is a soft delete with a 7-day grace period: signing back in cancels it, and data is removed permanently after 7 days.
Results
What it achieved
- Took the app from an offline scorer to an online, real-time, multi-user product in about two months
- A scoring engine covering extras, free hits, every wicket type, retirements, bowler limits, power plays and super overs
- ~23k lines of Dart across 21 screens, with row-level security on every table and automated Android builds
- Meets both stores’ in-app account deletion requirement















