ClubLadders
A production multi-sport platform for clubs to manage players, record singles and doubles matches, calculate Elo ratings, run tournaments, send notifications, and predict matchup win probability from historical match data — through workflows designed to stay clear and responsive across touch and desktop.
The problem
School chess and badminton clubs run ladders and tournaments on spreadsheets and group chats. Ratings drift, match history gets lost, and there's no fair, transparent way to seed a bracket. ClubLadders replaces that with a real product: clubs create invite codes, add members or guest players, record singles and doubles matches, maintain Elo history, run tournaments, and preserve historical results even when a player later claims an account.
What I built
- Production Next.js + FastAPI platform with Google OAuth, signed HTTP-only session cookies, invite-code onboarding, and public/private club controls.
- Competition workflows for singles, doubles, tournaments, club-vs-club challenges, leaderboards, seasons, scheduled sessions, announcements, and notifications.
- Responsive interaction system with immediate action feedback, touch-friendly controls, focused modal flows, motion restraint, and reduced-motion support so dense club operations remain understandable across devices.
- Production operations including analytics events, admin moderation, account export/deletion, maintenance mode, rate-limit abuse handling, and cached read-only PWA support.
Technical highlights
Guest-player claim flow
Players can be added to matches before they ever register. I modeled this with an XOR CHECKconstraint and an atomic claim transaction, so when an unregistered player later signs up, their Elo rating and complete match history transfer over intact — with no double-counting or orphaned records.
Deterministic Elo replay
Every player starts at 1200 Elo, with provisional K-factors for early games, lower stable K-factors after that, draw support, margin multipliers for score-based sports, and partner-adjusted doubles Elo. When a match is edited, deleted, or a rating anchor changes, the system replays match and tournament history chronologically so corrections do not create rating drift.
Interaction design across devices
I designed the interface around direct feedback and predictable spatial behavior: controls stay close to what they affect, destructive actions use focused confirmation flows, and mobile layouts preserve the same task hierarchy as desktop. Transitions use short, restrained movement, while reduced-motion preferences remove nonessential motion without removing useful status feedback.
Win-probability model (ML)
I trained a logistic-regression win-probability model on exported pre-match features using scikit-learn, and evaluated it with ROC-AUC and log loss. It surfaces a predicted probability for upcoming matchups — my CS & AI coursework applied to a real product.
Tested & CI-backed
A pytest integration suite runs against PostgreSQL 16 in GitHub Actions CI with Alembic migrations, covering auth, clubs, matches, Elo, tournaments, account deletion, bans, admin roles, push, Discord, analytics, sessions, seasons, exports, and security workflows.
Analytics and validation
Product validation
I used pilot commitments as the primary validation signal: four clubs agreed to test the product before the August 2026 rollout. That shaped the MVP around fast onboarding, transparent leaderboards, guest-player support, and match logging that works for both casual club play and organized tournaments.
Observability and analytics
The frontend uses Vercel Analytics and Speed Insights, while the backend records custom analytics events for product and admin workflows. That gives me enough visibility to debug onboarding, match recording, tournament usage, notification behavior, and abuse-control flows without relying only on server logs.
Model and reliability checks
For the win-probability model, I evaluate exported matchup features with ROC-AUC and log loss instead of relying on accuracy alone. For platform reliability, the backend has health checks, scheduled maintenance jobs, DB connection retries, SQLAlchemy pool pre-ping/recycle, Render keepalive pings, and regression tests for correctness-sensitive flows such as archived-member match recording.
Stack
See it in action
ClubLadders is live and piloting with four clubs this August.