Projects
All projects

CourtBot.

Know the moment a tennis court becomes free

  • Dart
  • Python
  • TypeScript
  • Flutter
  • Firebase
  • Selenium
  • Raspberry Pi

What is CourtBot

London's tennis booking scene is really bad. You refresh the page. There is a slot free. You click to book. Error. It's gone. Again.

As an avid tennis player in London, I found myself constantly frustrated by the challenge of finding available courts. The existing booking systems are clunky, and courts would get snatched up within minutes of becoming available. I would spend hours refreshing booking pages, hoping to catch a cancellation or a newly released slot.

CourtBot exists because of that pain. London tennis courts are in high demand, and booking systems seems to be great at one thing only: telling you everything is unavailable. It does not tell you when something changes. Courts do open up, but unless you're refreshing like it's a ticket drop, you'll never know. That's the core problem CourtBot sets out to solve.

Technical Architecture

CourtBot is built as a Flutter app, meaning one codebase can reach multiple platforms. On the backend, Firebase handles the heavy lifting — storing booking data, managing waitlists, and sending notifications when something interesting happens.

The slightly more unhinged part of the system was a Raspberry Pi that monitors the websites at regular intervals. When it notices a free slot, it reports back, and Firebase handles notifying the right people.

The entire Google development ecosystem like Firebase and GCS is really powerful and easy to use out of the box. I have not explored everything yet but some of the amazing free features I used were:

  • GCS notifications allowed me to set up a rudimentary PagerDuty-like system and Firebase
  • Firebase Crashlytics to track and fix app crashes

Why I Built It

I wanted a real excuse to properly explore Flutter and Firebase, not just build another demo app that fetches fake data and lives forever on my laptop. I wanted something with real users, real constraints, and real consequences if it broke (like not playing tennis). Also I get to publish an app to Apple App Store and Google Play Store! FYI, It's a bureaucratic nightmare.

This problem turned out to be perfect. It's small enough to be understandable but messy enough to be interesting. That meant I could experiment with things like Firestore data modelling, push notifications, background jobs.

It also helped that the pain point was personal. Every feature in CourtBot is something I genuinely wanted myself, which is a great forcing function for finishing things. When you're building a tool you actually plan to use, “good enough” is not really good enough.

Lessons and Interesting Tidbits

  • Tennis courts are freed up way more often than you think—just not at times humans are watching.
  • Booking websites change layout more often than tennis rules change.
  • A Raspberry Pi is perfectly capable of consistently scraping a web page.
  • “Just refresh the page” is terrible product advice. Looking at you LTA.