Building an app that scratches your own itch has never been easier. All I had was a link, two station names and “if that would not be too much”. From that I got a detailed spec, and an afternoon later a live map of my corner of London was running on its own domain. Every tube train, bus and plane on it is real and moving.
Here’s how it went, from the first vague message to the deployed app. I’ll cover the spec, the iterative build, the open data that made it possible, and the small Polish VPS it runs on.
It started, like most things here, with a coffee and some scrolling.
Smelling the Beans: Finding ZONE ONE
One evening I came across ZONE ONE by James Potter. It’s a live map of central London where every tube train, bus, mainline train, riverboat and aircraft on screen is real and moving in real time. Hover over a train and you see where it’s going. Click a station and you get its departure board. Click a traffic camera and you get its live picture.
I watched it for far too long. Then I had the obvious thought: I want this, but for where we live.
Central London is lovely, but my family doesn’t wait for buses at Oxford Circus. We wait for them in Loughton, Buckhurst Hill and Woodford, at the far north-east end of the Central line where London turns into Essex and Epping Forest.
Why We Wanted It: Watching “Your” Bus Move (or Not)
There’s a very particular feeling we know from Kraków. The city has an app that shows public transport moving live on a map “KRK pod ręką”. Whenever we’re there, we use it all the time. You stand at a stop, open the map, and watch your tram or bus crawl towards you. Sometimes it moves. Sometimes it sits at the same junction for four minutes, and at least you know why you’re still standing in the rain. 🙂
A countdown on a stop display is one thing. Seeing the actual vehicle on its actual road is different: it’s calming, it’s honest, and the kids love it.
So the goal was never “rebuild ZONE ONE”. It was simpler and more personal:
The brief, in one line: a live map of our stretch of London, built for me and my family, so we can see our bus and our tube train on the move.
The Vaguest Recipe Ever: My Initial “Spec”
This is the whole of what I gave Claude Code at the start. It is almost embarrassing, I didn’t tidy it up for the blog:
I wonder what would it take to replicate this project:
https://london.jamespotter.dev/
[ZONE ONE description and data credits pasted from the site]
But done for the section containing:
- Loughton
- Buckhurst Hill
And if that would not be too much
Up to
- South Woodford
That’s it: a link, a pasted description, three station names and a bit of hesitation.
Grinding the Beans: From Vague Idea to a Detailed Spec
This is the part that surprised me most. Today’s models have become good enough that a vague instruction plus a short discussion turns into a real, detailed specification. I don’t mean a vague “here’s a plan”. I mean a spec you can build from.
Claude didn’t just guess. It went and checked the live APIs and wrote down what it found. The resulting SPEC.md contains, among other things:
- The exact area: a bounding box of about 7.5 km × 5.2 km from Debden to South Woodford, plus a 1 km margin so vehicles slide in from the edge instead of popping into existence.
- Which ZONE ONE layers make sense here. Tube trains, buses, aircraft and traffic cameras: yes. Riverboats: no, because the River Roding isn’t navigable. Ship tracking: “Nothing to track”. I laughed at that one.
- A research log of real API calls, with measured numbers. One call to the TfL Central line endpoint returned 559 predictions for 54 trains (524 KB). It found 328 bus stops and about 20 regular bus routes in our area, and about 890 traffic cameras across London.
- Quirks found in real data. For example, the
directionfield is sometimes missing (45 out of 559 predictions), and the same train’s “current location” text differs depending on which station you ask. - The hard part, spelled out: positioning algorithms. TfL doesn’t give GPS for tube trains, only “arrives at station X in N seconds” predictions. The spec explains how to turn those into a smooth position along the real track, including the tricky Woodford junction, where Hainault-loop trains split off from Epping trains.
- Risks, milestones, testing and licences: including that trains must never move backwards and must never be drawn more than 50 m off the track.
Discussing before instructing
It also listed open decisions for me (include the Overground line or not, where to host, whether to show non-TfL Essex buses), which is exactly what a good colleague would do.
Tip: treat the model like a senior engineer you’re briefing over coffee. A vague brief is fine, as long as you answer its questions and let it go and look at the real data before it writes anything down.
And the important part: the spec was enough to build the app. I didn’t have to keep re-explaining what I meant. When I came back to the project later, the spec was the single source of truth for both of us.
Meanwhile, at the Café Counter: Setting Up a Mikrus VPS
While Claude was busy researching and writing the spec, I did my bit of parallel work: I sorted out somewhere for this to live.
I went with Mikrus, the small VPS service run by Jakub Mrugalski. If you’re Polish and into tech, you’ve almost certainly heard of him. Mikrus is cheap, simple and built for exactly this kind of hobby project.
There are a few quirks to know about:
- Each server is an unprivileged LXC container, so there are no kernel modules and no
sysctlchanges. - It’s IPv6-first. On the shared IPv4 you get a few assigned ports (for example
20000+IDand30000+ID) instead of 80 and 443. - In return you get a free
*.mikrus.cloudHTTPS subdomain, and with Cytrus you can point your own domain at it.
The real game changer, though, is the Mikrus MCP server.
What’s MCP? The Model Context Protocol is the standard way to give an AI assistant tools. The Mikrus MCP server gives Claude tools such as
exec(run a command on the server),upload,porty(check your public ports) anddomains.
Here’s the order of events, all within the time Claude spent writing the spec:
- I bought a new VPS.
- I enabled the MCP server in the Mikrus panel.
- I added it to Claude Code, along with the Mikrus skill (a short guide to the platform’s rules: LXC limits, IPv6, which port maps to which URL).
So by the time the spec was finished, Claude could already reach the server. It didn’t need me to copy anything around or SSH anywhere. Deploying was just another step in the plan.
The first deploy landed 15 minutes after the first commit. A Node service runs under systemd, and a small scripts/deploy.py builds the app, uploads it through the MCP, switches the release and restarts the service. Later I added my own domain, map.zagor.org, via Mikrus Cytrus with DNS at Cloudflare. We also reboot-tested the server: the map came back by itself about 7 seconds after boot.
My take: an MCP for your hosting provider is a godsend. It turns “and then I’ll spend an evening on deployment” into “deployed, here’s the link”. If your VPS provider doesn’t offer one yet, ask them for it.
Single Origin: Why London Is a Dream for Open Transport Data
A quick appreciation, because none of this works without it: London has some of the best digital coverage of public transport anywhere.Almost everything you’d want is open, documented and free:
- TfL Unified API: tube, bus, Overground, stop sequences and traffic cameras (JamCams). A free key gives you 500 requests per minute. One call returns every prediction for the whole Central line. The app uses about 12 TfL calls per minute in total, whether one person is watching or a hundred, because the server caches everything and streams it to browsers.
- Bus Open Data Service (BODS): the Department for Transport’s national bus feed for England, with real GPS positions. The spec flagged it as an open question whether London buses appear in it at all. A quick test answered it: they do. One call over our area returned about 160 buses. Their registration plates match TfL’s vehicle IDs, so the two feeds join directly. It also brought in the non-TfL Essex operators (Arriva, Stephensons, National Express coaches), which TfL doesn’t cover.
- OpenStreetMap: the actual track geometry, with eastbound and westbound Central line tracks mapped separately, platforms numbered, and even Loughton sidings.
- adsb.lol + adsbdb: community aircraft tracking. Our area is busy with Stansted, City and Heathrow traffic, and the Lambourne Heathrow holding stack sits just east of the frame.
Having lived with transport apps in a few countries, I can tell you this isn’t normal. It’s a real gift to people who tinker. 🙏
One Shot at a Time: Building It in Thin Slices
We agreed on one rule early on: build it iteratively, starting with the most basic version, and deploy every slice before starting the next one. No big bang. Each step had to be something I could open on my phone and use.
Here’s how the weekend afternoon actually went (times from the git log, all on one day):
| Time | Increment | What it added |
|---|---|---|
| 14:57 | 1. Live tube | Dark map, 3D buildings, Central line track from OSM, live trains animated along it, station departure boards |
| 15:12 | 2. Deploy | Running on the Mikrus VPS over HTTPS |
| 15:17 | 3. Aircraft | Planes from adsb.lol, with airline, route and photo on hover |
| 15:38 | 4. Buses | 12 main TfL routes, placed from arrival predictions, with bus stop boards |
| 17:44 | 4a. Real bus GPS | BODS positions snapped to the route line, arriving at stops on TfL’s predicted times |
| 18:03 | 5. Traffic cameras | 27 TfL JamCams around Charlie Brown’s roundabout and the A406, with stills and video clips |
| 18:42 | 7. About page and “tycoon” look | A switchable retro look with pixel-art vehicles drawn in code (original artwork, nothing borrowed) |
| 19:02 | 8. Overground | Weaver line trains at Chingford |
Sipping not rushing
Increment 6 (Overture buildings, polish, Essex buses) is still in the backlog, and that’s fine. That’s the point of slices.
A few things I liked about working this way:
- The first version was useful within minutes. Seeing Central line trains glide between Loughton and Buckhurst Hill was already the thing I wanted.
- Deviations were written down, not hidden. For example, increment 1 used plain MapLibre layers instead of deck.gl, because for about 15 trains it wasn’t needed. The spec records why.
- Real-world problems showed up early. adsb.lol started rate-limiting the server (HTTP 429s) shortly after launch. We added backoff, honoured
Retry-After, polled less often, and let the browser dead-reckon each plane for up to 60 s between updates. The fix and the reasoning went into the spec’s risk table.
Rule of thumb: a deployed slice beats a perfect plan. Every slice that lands is a slice you can show your family.
The Tasting Notes: What It Actually Does
Open map.zagor.org and you’ll see:
- Central line trains moving along the correct eastbound or westbound track, taking the right fork at Woodford, and never moving backwards.
- Overground trains on the Weaver line at Chingford.
- Buses, mostly on real GPS, steering smoothly towards the next stop so corrections slow them down instead of making them jump. Non-TfL operators are shown in blue.
- Aircraft with short fading trails, plus airline, route and photo when you hover.
- Departure boards when you click a station or a bus stop.
- Traffic cameras with the latest still and a play button for the clip.
- A retro “tycoon” look you can switch on, which the kids insist is the only correct way to view it.




And yes, the original use case works. We now stand at the bus stop and watch the W14 sit at the lights. 🙂
Useful Links
| Category | Description | Link |
|---|---|---|
| Inspiration | ZONE ONE by James Potter | https://london.jamespotter.dev/ |
| The result | My live map | https://map.zagor.org/ |
| Hosting | Mikrus VPS by Jakub Mrugalski | https://mikr.us/ |
| AI assistant | Claude Code | https://claude.com/claude-code |
| Tube, buses, cameras | TfL Unified API | https://api.tfl.gov.uk/ |
| Bus GPS | Bus Open Data Service (DfT) | https://data.bus-data.dft.gov.uk/ |
| Track geometry | OpenStreetMap | https://www.openstreetmap.org/ |
| Aircraft | adsb.lol / adsbdb | https://adsb.lol/ · https://www.adsbdb.com/ |
| Map rendering | MapLibre GL JS + OpenFreeMap | https://maplibre.org/ · https://openfreemap.org/ |
Lessons Learned From This Coffee Journey
- A vague idea is enough to start. A few lines and some honest back-and-forth produced a spec I’d be happy to get from a colleague.
- Let the model look at real data before it plans. Measured numbers and observed quirks made the spec buildable instead of hopeful.
- The spec is the product’s memory. Decisions, deviations and lessons (like the adsb.lol throttling) went back into it, so nothing lived only in chat history.
- Start embarrassingly small and ship every slice. One train line on a dark map was the first win. Everything else was a bonus.
- Hosting is no longer the boring hurdle. With the Mikrus MCP, deploying became a step the assistant just does.
- Open data is the real hero. TfL, BODS and OpenStreetMap made a family side project possible in an afternoon.
By the time the Weaver line trains appeared at Chingford, my coffee was long cold, but the map was alive. A small VPS somewhere in Poland now polls London’s transport feeds every few seconds so my family can see whether the bus is coming.
There has never been a better time to build the small, slightly silly tool that only you need. Find the itch, write the vague first message, and see how far it gets you.
What would you put on your own live map? Your town, your commute, the bus that never comes? Tell me in the comments.

