Case study 02  ·  Own product  ·  Live

courtScore

It started as a fix for one pickleball group's unfair rotations. Two years and six versions later, it's a tournament platform for pickleball and badminton that organizers use to run real events, with live scores on everyone's phone.

RoleProduct, design, build and ongoing maintenance. Solo.
TimelineOctober 2024 to now
StackPython, Flask, PostgreSQL, Mailgun, Web Push, Railway
Live sitecourtscore.ca ↗
courtscore.ca
courtScore round robin fixtures on desktop
198games scored live
63players across 30+ tournaments
900+automated tests
600+commits since October 2025
01The problem

Somebody always sat out twice. Somebody always got the same partner.

Running a social round robin meant one person juggling names on a whiteboard, guessing who should play next and tallying scores by hand. Pairings drifted, sit-outs weren't fair, and nobody trusted the standings at the end of the night.

Before
  • ×Rotations planned on a whiteboard
  • ×Same partners, same opponents
  • ×Scores tallied by hand
  • ×Results lost when the session ended
After
  • →Fair rotations generated in a tap
  • →New partners before any repeats
  • →Scores entered from any phone
  • →Results emailed and saved to profiles
02How it got here

Six versions in two years

Every version was used at real sessions, and each one fixed what players complained about in the last. The algorithm survived every rewrite. Almost nothing else did.

  1. Oct 2024
    iOS · SwiftPickleball SchedulerFirst attempt: an iPhone app to plan one group's rotation.
  2. Oct 2024
    iOS · SwiftUITwo SwiftUI rewritesRebuilt twice the same month to get the pairing logic right.
  3. Dec 2024
    HTML · JavaScriptWeb versionMoved to the browser so anyone in the group could open it.
  4. 2025
    Python · FlaskPB SchedulerThe first server version, run at sessions.
  5. Oct 2025
    Flask · PostgreSQLShuttleSchedulerOpened up to badminton, with saved players and finals.
  6. Oct 2025 to now
    Flask · PostgreSQL · RailwaycourtScoreRebuilt and rebranded: accounts, guests, three modes, live scores.
03What I built

What it does

Three tournament modes exist because three different organizers asked for three different things, not because a roadmap said so.

01

Run the event

  • →Rotating, fixed-team and manual modes
  • →Groups, playoff brackets and best-of formats
  • →Co-admins and an organizer-only score lock
  • →No account needed to start as a guest
02

Play the event

  • →Scores entered from any phone
  • →Live standings and finals
  • →Share link for spectators
  • →Installable app with push notifications
03

After the event

  • →Results emailed to every player
  • →Global leaderboard and player profiles
  • →Tournament history and PDF export
  • →Super-admin portal for oversight
04The hard part

Fair rotations for any number of players.

The scheduler is the piece that started it all. For every game it decides who plays, who partners whom and who they face, so that over a session everyone gets a fair share of games and new partners before anyone repeats.

Rotating partnersFixed teamsManualGroupsPlayoff brackets
1
Sit-outs first

Players who sat out the last game get priority for the next one.

2
New partners

A pair can only team up again once both have partnered everyone else.

3
Fresh opponents

Teams that already met are avoided while new match-ups exist.

4
Live standings

Every score updates standings on every phone in the room.

Odd numbers: sit-outs rotate so the extra player changes every game.
Guardrail: generation is capped, so even a 100-player event can never spin forever.
05How it's built

Engineering decisions

Pure algorithm

The scheduler is plain functions with no database calls, so it's tested on its own.

Guests first

Anyone can run a full event without signing up, then claim it later.

Locked results

Organizers can lock scores so a finished game can't be quietly edited.

Self-cleaning

Unclaimed guest events expire on a schedule, handled by a cron job.

Email that lands

Results go out through Mailgun with a fallback provider.

Feels native

A service worker and push notifications let it install and behave like an app.

06Screens
courtScore on three phone screens
Fixtures, rankings and a personal record, made for a phone at the court.
The courtScore leaderboard on a phone
Rankings across every tournament, by titles or by win rate.
A personal record in courtScore on a phone
A personal record told in plain sentences, not a table of numbers.

It started with one group's sessions and now runs full tournaments.

courtScore has scored 198 games for 63 players across more than 30 tournaments. I still run it, and I keep shipping what players and organizers ask for.

Abbas Virjee · Toronto, Canada[email protected]