A full-stack tennis club platform where players register, record matches, and earn a live ranking. Singles and doubles support, club/group management, head-to-head history, and searchable leaderboards — all backed by a FastAPI backend with JWT auth and a MySQL database.
Every match recorded feeds a live ELO-style strength index — so the leaderboard reflects who's actually winning, not just who's played the most.
Each match result updates both players' TSI score immediately. Win against a higher-ranked opponent and your rating climbs faster — lose to a lower-ranked one and it drops more. Always current, never stale.
Record and track both match formats with separate leaderboards. Doubles results attribute ratings to each individual player, keeping the index meaningful across both formats.
Organise players into clubs and groups. Club admins manage membership; players can search for clubs and request to join. Rankings are visible across the whole platform and within each club.
Every player gets a profile with their full match history, current TSI score, win/loss record, and head-to-head breakdown against any opponent they've faced.
Browse and search the full player list by name or club, sorted by TSI ranking. Filter by format (singles/doubles) or scope to your own club's standings.
JWT-based authentication with registration, login, password change, and password-reset via email. Players own their own data — no admin required to update a result.
Built to run self-hosted with Docker Compose — no managed services, no cloud lock-in.
Built with React 18, React Router, and MUI — a responsive SPA with chart-based player stats (Chart.js), clean data tables, and a mobile-friendly layout served via nginx.
A Python FastAPI REST API with full CRUD for players, matches, clubs, and rankings. JWT authentication, bcrypt password hashing, and configurable SMTP email for password resets.
Relational schema covering players, match results (singles + doubles), club membership, and computed TSI scores. Fully schema-migrated on first boot via Docker init scripts.
Three-service compose stack (frontend, backend, MySQL) with health-checked startup ordering, persistent volumes, and environment-based config for JWT secrets and SMTP credentials.
Register your club, invite players, and start recording matches — the leaderboard updates in real time after every result.
Launch Tennis Strength Index →