← Back to Projects

Tennis Court Booking Bot

A personal chat bot that checks, books, and auto-hunts tennis courts in Ghent. Designed as a conversation and built end-to-end with AI tools.

Role: UX Designer & AI-assisted build β€’ Timeline: 2026 β€’ Type: Personal tool (Telegram)
Tennis Court Booking Bot conversation on Telegram

The Challenge

Booking a public court in Ghent runs through a city website β€” one I'd already picked apart in my City of Gent Sports Booking case study. So this time I asked a different question: what if booking didn't need the website at all?

The Solution

I decided to create a chat bot that would handle the entire booking process. This is conversational UX doing its job. Booking a court used to mean working through the Stad Gent website screen by screen; now it's a short exchange with a chat bot on Telegram. Here's the difference, the number of moves between "I want a court" and "it's booked."

Approach Taps Screens Hands-on
Stad Gent website ~14 8 ~2 min
Chat bot 3 1 ~15s
Screens are measured. Stad Gent's documented 8 steps flow vs. one chat. Taps and times are approximate. The bot books in the background (~60–90s), so "hands-on" is active effort.

I mapped the old flow, then deleted everything I could

  1. 01

    Audit the original

    Walked the real booking task end-to-end and logged every tap, reload, and choice.

  2. 02

    Find the irreducible inputs

    Stripped it down to what actually defines a booking: when β€” and that's nearly it. The rest are defaults the system should hold for me.

  3. 03

    Design the dialogue

    Scripted the conversation so the bot asks only what it can't assume, and confirms in one clear step.

  4. 04

    Build & live-test

    Shipped it for myself and refined the wording against real bookings until it felt effortless.

Designing the Conversation

A chat interface has no buttons, layout, or visual hierarchy to lean on. Every design decision lives in the wording, the order of messages, and the moments where the bot pauses to check in with me. These were the interaction-design choices I cared about most.

A list of all available commands

Even as the only user, I didn't want to memorise anything to use my own bot. A chat has no buttons to explore, so I made the words do the work.

  • /start lists every command with real examples, so I never have to remember them, even coming back after a few weeks
  • I can type a date however I think of it: 06 december, dec 6 after 7pm or 13-12-2025
  • A natural language parser reads what I wrote, so I don't have to follow a strict format
Telegram chat showing the /start command and the bot's full command menu

Confirm before booking

Booking and cancelling cost real money and a real slot, so I never let them happen on the first message and without my confirmation.

  • The bot plays back exactly what it understood: court, date, time. Then it waits for my yes
  • It's like the confirm step before a purchase, that's where I catch a misread date
  • Slow work is narrated:
    πŸ” checking… β†’ βš™οΈ processing… β†’ βœ… confirmed
    so silence never makes me think it broke
Telegram chat confirming a booking β€” the bot plays back court, date and time, waits for a yes, then confirms

See and cancel bookings without leaving the chat

The conversation covers the whole booking lifecycle, not just making a reservation, but reviewing and undoing one too.

  • /reservations lists all my active bookings at a glance: court, date and booking number
  • Cancelling asks me to confirm first, just like booking, so I never remove one by accident
  • It all stays in one thread; I never log into the city website to manage a booking
Telegram chat showing /reservations listing active bookings and /cancel removing one

I let the bot do the checking

I didn't want to keep refreshing the site for a free court, so I let the bot do it. I give it a date, and it looks every 15 minutes β€” then books the first slot it finds between the range I specified.

  • I type /search with a date and reply yes to start
  • It checks for a free court every 15 minutes, so I don't have to
  • As soon as an evening slot opens, it books it and messages me
  • But if a slot starts within a few hours, it just tells me instead of booking. The website only lets me cancel for free up to 2 hours before start, so the bot won't lock me into a time I might not want
Telegram chat showing the /search command β€” confirm, then the bot checks every 15 minutes and books automatically

The Bot in Action

One real booking on my own phone, from request to confirmation β€” with the design decisions marked.

A real booking on Telegram: the bot plays back court, date and time, waits for a yes, then narrates checking, processing and confirmation 1 2 3
  1. 1

    Plays the booking back β€” court, date and time β€” so I catch a misread before anything happens.

  2. 2

    Nothing books without a plain "yes" β€” the only irreversible step is always mine to approve.

  3. 3

    It narrates each step β€” checking, processing, confirmed β€” so a pause never feels like it broke.

Designing and Shipping with AI Tools

I'm a designer, not a backend engineer, but AI tools let me take this from idea to a running service. I used them as a pair-builder: describing the behaviour I wanted, reading and steering the code, and making the product decisions myself.

How a request travels

MeTelegram chat
β†’
Bot logicparse intent
β†’
Automationdrives the city site
β†’
Confirmationback in chat

Because the website has no public API, the booking itself is done by browser automation that logs in and clicks through the real site, and a natural-language model interprets the date/time phrasings. My login stays in a secrets manager and never in the code.

Telegram Bot API Claude Cursor Gemini (natural-language parsing) Python Selenium Google Cloud Run

Automating with a Clear Conscience

Automating someone else's website deserves judgement, not just enthusiasm. Before building, I scoped the project so it stays personal and fair.

πŸ‘€

Personal use only

One account, my own credentials, for booking courts I actually play on. No reselling, no profit, no second users.

🀝

A gentle footprint

One user, polling at a 15-minute cadence with retry limits: designed to behave like a patient human, not to hammer the site.

πŸ”

Credentials kept safe

Login details live in a secrets manager and are git-ignored. Never committed to the repo, never shown in the interface.

Outcome & Reflection

I now book courts by sending one message. The whole thing runs in the background at no cost. A few things stuck with me: