Building TrainSpotterAI: How to Hunt Trains like a Pro for your kids (without looking like a commuter)
Most train apps are designed for commuters—the kind of people who care about "delayed by 4 minutes" because they might miss their connecting train to Croydon. They are not designed for the enthusiasts, the photographers, or the mildly obsessive who just want to know: When is this massive chunk of steel going to roar past my face? Or even for parents who just want to keep their toddlers entertained.
Enter TrainSpotterAI: a native Android app built specifically to bridge the gap between platform boarding times and trackside reality. It’s like Tinder, but instead of swiping on people who "love travel and dogs," you’re swiping on Class 800 Azumas. And honestly, the trains are much more reliable (most of the time!).
The Core Experience: Beyond the Platform (Where the Real Fun Is)
Standard departure boards only care if a train stops. If a non-stop express is hurtling through at 125 mph, the average app just shrugs and pretends it doesn't exist. TrainSpotterAI doesn't do shrugs... I'm reliably informed that the underlying API will soon acknowledge passing expresses!
Using your GPS, the app sniffs out the nearest National Rail stations and curates a tight, 5-to-15-minute "spotting window."
But the real crown jewel is the Trackside Estimate card. Instead of telling you when a train is stopping at a station three miles away, it does some high-speed mathematical wizardry. By calculating the distance and time between the queried station and the next stop on the train’s itinerary, it interpolates exactly when that glorious hunk of metal will pass your specific, shivering body. It’s a literal countdown to train-spotting glory.
The Architecture: Keeping the Secret Sauce Secret (And Free)
Building an app is fun until you realise you have to pay for data. Our primary data provider, the excellent headcode.dev, has one very reasonable, but very strict rule: Do not put your API keys in the client-side code.
Because if you do, some clever script kiddie will steal it, run up a £10,000 bill, and leave you living on instant noodles.
To prevent financial ruin, we built a Cloudflare Worker (using the ultra-speedy Hono framework) to act as a backend proxy. This does three vital jobs:
Security: It keeps our precious API keys locked away in a digital vault on the server, far from prying eyes.
Performance: It handles rate limiting so our users don't accidentally DDOS our data provider.
Data Transformation: It does the heavy lifting of figuring out where the next station is and prepping the coordinate data before sending it to your phone, saving your battery life for taking photos.
Upstash Redis: Because I'm Cheap and Upstream Limits Exist
Because headcode.dev enforces account-wide rate limits, we can’t just let the app ping their servers every time a user blinks. To keep things running smoothly, I hooked up Upstash Redis to run a dual-layer caching strategy:
The Board Cache (20 seconds): If you and three other nerds are standing at the same bridge, you don't all need to make fresh requests. We cache the station board for 20 seconds.
The Station Info Cache (30 days): Station coordinates and names don't change unless someone physically moves a station (unlikely, even for Network Rail). We cache this static data for a whole month.
And if the upstream provider goes down? We’ve got "stale-if-error" logic. The app will happily serve you cached data up to 3 minutes old. It’s better to have slightly old train data than to stare into a blank screen of digital nothingness.
Under the Hood: Pure, Unadulterated Kotlin
No cross-platform compromises here. No React Native (although I did start there, but soon got bored of waiting for it to build!). No Flutter (maybe next time!). I wanted this thing to be fast, so TrainSpotterAI is written in native Kotlin and Jetpack Compose. (thanks Claude!)
The Math: The app handles all the "spotting window" geometry locally. It uses Haversine formulas (the math used to calculate distances on a sphere) to figure out how far you are from the tracks.
The Data: Instead of begging the backend to search for stations every time you move ten feet, the app carries a local database of UK stations (derived from NaPTAN) and scans it locally.
The UI: You get a clean List tab for a quick glance, and a Map tab (powered by OpenStreetMap/osmdroid) to visualize the rail network around you in real-time.
Current Status: Shhh, It’s a Secret (For Now)
Right now, TrainSpotterAI is in a Soft Launch phase, distributed strictly having the apk shared with you... I might get it into Google Play in due course.
Why the secrecy? Because the headcode.dev API is still technically in "Alpha," and we need to make sure our caching layers actually hold up before we unleash a horde of enthusiastic train spotters on to the live servers. Big shout out to Aran Wilkinson who is the creator of headcode.dev API and has rapidly enabled my access and fixed up a couple of bugs as well as promising exciting new features soon!
But watch this space. Soon, you’ll never have to guess whether that distant rumble is a freight train or just thunder again. Stay tuned!






Comments