Skip to main content
Apps

EquiCalendar: Unifying UK Equestrian Competitions Across Scattered Sources

Since my daughter started competing on her pony, I’ve spent countless hours searching for her competitions. Not preparing her for them. Not coaching. Just finding them. She’s competing in tetrathlon — four disciplines, which means four different competition calendars scattered across at least that many websites.

Except it’s not four. It’s dozens.

British Showjumping has their own system. NSEA has another. Equipe Online, Horse Monkey, Horse Events, Kelsall Hill, Epworth, Pony Club, HorsEvents, NVEC, My Riding Life, EquiLive, British Eventing, EquoEvents, Ashwood, British Dressage. And that’s just the major ones. Each displays information differently. Each one formats dates differently. Each one has a different way of indicating whether a competition is actually running or cancelled. Each one requires checking separately to know if there’s anything near you.

The real problem isn’t the number of websites. It’s the fragmentation. She can’t see what’s happening across all disciplines in one place. I can’t filter by venue location. Neither of us knows at a glance what competitions are actually geographically reachable.

Many Sources, One Calendar

What existed was a spreadsheet problem masquerading as a coordination problem. The infrastructure for competition listings was there — all these sites publish their data. But that data was siloed. Each website serves a different segment of competitors (British Dressage for dressage-focused riders, Showjumping for jump competitions, Pony Club for youth), and nobody’s built the aggregator.

So I did.

EquiCalendar scrapes these sources on a schedule. It normalises the inconsistency — competitions get standardised fields, dates, disciplines, venue information. It geocodes every venue using postcodes.io so you can search by location. It provides a single calendar you can filter by discipline, by pony, by venue, by date.

For a rider, that means: “Show me all competitions within 20 miles of home, running in the next three months, that include showjumping.” One query instead of manually checking dozens of websites.

Normalising Chaos: One Venue, Many Names

Once the scrapers started pulling data, a problem emerged immediately. The same venue appeared under different names across different websites. Addington. Addington Manor. A EC Addington. Each source had its own convention for naming. Some included postcodes, some included house names, some just listed coordinates without any name at all.

Without normalisation, a rider searching for “competitions at Addington” would only see the ones that website happened to call “Addington” — and miss the same venue listed as “Addington Manor” on another site.

So I built an alias system. Each unique venue (determined by postcode and geographical coordinates) can have multiple names. As data comes in from the scrapers, it gets deduplicated against existing venues. When a new name is encountered, it gets added as an alias rather than creating a duplicate venue record. This way, geocoding provides the source of truth — coordinates don’t lie about location the way names do.

The Unlock Was Geocoding

The scraping itself was straightforward. FastAPI with Python, Docker containers running Celery Beat for scheduled jobs, Postgres to store the normalised data. A parser for each source, each one understanding that website’s HTML structure. They run every four hours and pull fresh competition listings.

That’s all fairly mechanical. The real unlock was geocoding.

Most UK competition websites include a postcode. Most don’t include coordinates. Postcodes.io changed everything. Once I had coordinates for every venue, suddenly the app could answer location-based queries. “Competitions near me” wasn’t a feature I’d have to build custom — it was a natural consequence of having latitude and longitude.

Everything else flowed from that. Filter by distance. Sort by travel time. Show a map. None of that would have been straightforward without the geocoding layer.

What Actually Exists

EquiCalendar is a FastAPI application running on a standard Python stack. The frontend is deliberately minimal — a searchable, filterable table of competitions with venue, date, discipline, and distance from a user’s postcode. The UI isn’t glossy. It doesn’t need to be. The value is in having all these sources in one place.

The app stores competition listings in Postgres. The scheduler runs the scrapers every four hours, updating the table with new competitions, marked cancellations, and venue information changes. When a site removes a competition listing (usually because it’s expired), the scraper marks it as historical rather than deleting it.

Users can filter by discipline (dressage, jumping, cross-country, showing), by pony (the filters remember your stable), by postcode radius. The table sorts by date, distance, or venue name. That’s enough to answer the question: “Where can I ride next?”

What’s Next

The current version solves the core problem — visibility. But there’s more that could happen. Calendar app integrations so competitions sync to Apple Calendar. Travel time estimates from home to venue. Difficulty predictions based on competition history. Integration with results databases so you can see what level a competition typically runs at.

None of those are essential to the core product. “Where can I ride?” is the question that needed answering. EquiCalendar answers it.

The Framing Lesson

Sometimes the value in a product isn’t in the features. It’s in the perspective. A feature-by-feature breakdown of EquiCalendar isn’t particularly impressive — multiple scrapers, a Postgres table, a filtered view. The value is in what those features do together: they give riders unified visibility across a fragmented market.

The same could be said about a lot of software. The individual pieces are often mechanical. What matters is what they mean when you put them together.

EquiCalendar is available as a web app.