I want to write down how this actually went, while it's fresh, because the finished pages make it look cleaner than it was. In one week, KaNairo — our Nairobi digital twin — went from a stylized 3D diorama of about a thousand CBD buildings to a real, pannable map of 1,277,511 buildings covering the whole metro, with a working billboard-rental business on top and three Working Papers documenting the pipeline. This essay is the part the papers leave out: the order things actually happened in, what broke, and what I'd tell someone attempting the same thing for their own city.
It started with a joke that needed real estate
The chain of causation is honestly a little absurd. We had a $1.99 joke — rent a billboard in the 3D scene — that sold slots on an invented ring road with fifteen fixed positions. Making the joke better meant making the real estate real: actual streets, actual coordinates, "what's available and where." That pulled in OpenStreetMap road data and a real map (MapLibre, OpenFreeMap tiles — no API keys, which matters when you run everything on one small server). Suddenly billboards sat on Uhuru Highway because the data said Uhuru Highway was there.
And once one layer was real, the unreality of the rest started to itch. The 3D scene's thousand buildings were real too — but only for 1.5 square kilometers of a city of hundreds. The map claimed "Nairobi." It showed the CBD. That gap is the whole project, in miniature: the difference between looks like and is.
The week's actual sequence, with the failures left in
The CSP fight. The first time the real map loaded, it didn't — a blank beige rectangle. Our site ships a strict Content-Security-Policy, and the tile host wasn't on the allowlist. The fix was two lines, scoped to just the map pages. Then it happened again on the second map page a few days later, because I'd scoped the first fix to exactly one URL path. Strict security policies are like good fences: you notice them exactly as often as you climb over them.
The SSL certificate maze. Both the Overpass fetch script and the Overture download tripped on the same macOS Python quirk — no usable certificate bundle for urllib. Same fix twice (certifi), because I didn't generalize the first time. There's a lesson in there I keep re-learning.
The 406 that wanted a name. Overpass rejected our building-inventory fetch with HTTP 406 until the request carried a proper User-Agent identifying who we were and how to reach us. Fair enough — free public infrastructure deserves to know who's leaning on it. It's the polite-society version of an API key.
The data pull that just… worked. Against expectations, the big one was easy: Overture Maps shipped 1.27 million building footprints for a bounding box covering Karen to Embakasi in a few minutes, as GeoParquet, free. Ten years ago this dataset wouldn't have existed; five years ago it would have been a grant proposal. This is the part I want other African builders to hear: the data is sitting there now. The moat isn't access anymore. It's the will to do something with it.
The Mathare check. While researching sources I hit an academic paper noting Mathare had no buildings in OpenStreetMap. We had the data on disk to check that claim in minutes, so we did: it's outdated — Mathare has 5,061 buildings in the merged dataset now — but 70% of them exist only because Google's satellite model saw them. Kibera, same informality, same city: 82% human-mapped, because Map Kibera has been at it for fifteen years. That one comparison became its own paper, and it's the finding from this week I actually care most about. Volunteer map coverage tracks where attention already went. Build on it alone and you inherit its blind spots.
The tile store. You cannot hand a browser 1.27 million buildings in one file. (The v1 scene hands it a thousand, in one file, and that's fine. Scale changes kind, not just degree.) The answer is the oldest trick in web cartography — cut the city into tiles, stream only what's visible — applied to building footprints: a 400m grid, 8,536 tiles, one SQLite file, 68.5MB. The map fetches maybe twenty tiles for a typical viewport. Pan, and it fetches the next few. "1:1 but light" stops being a contradiction the moment you stop loading the whole city at once.
The heights problem, deferred honestly. Of 1.27 million buildings, 4,203 have a real height on record — 0.3%. A validated fix exists (Google's height raster, 2.5m accuracy for Nairobi specifically, per peer-reviewed work), but it needs Earth Engine access we haven't set up. The choice was: block everything on that, fake it and say nothing, or estimate visibly. We estimated — settlement patterns, distance from the core, land-use — and every single building carries a confidence label, rendered as color on the map. 73.5% of the city is the lowest tier. That number is in the paper, in the first table, not a footnote. If the twin's whole pitch is honesty about what the city knows about itself, it doesn't get to lie about what it knows about the city.
What I'd tell someone doing this for Kampala or Kigali or Lagos
Three things.
First: start with the joke, or whatever your version of the joke is. The billboard product forced every piece of real infrastructure this week rests on — real coordinates, real streets, a working payments loop, an inventory model. A "civic data platform" pitch deck forces nothing. Small real things beat large imagined ones.
Second: merged data or you're mapping attention, not the city. If we'd built on OpenStreetMap alone — the obvious, default choice — Mathare would be nearly invisible on our map, and we would never have known, because absence doesn't announce itself. The places with the least institutional attention are exactly the places single-source data misses most.
Third: label your uncertainty and ship. The alternative to estimated-with-confidence-tiers wasn't measured heights. It was either nothing at all, or estimates dressed up as facts. Naming what you don't know is what buys you the right to ship before you know everything — and it converts every future data improvement into a visible upgrade instead of a quiet correction.
Where this leaves the twin
The render half of the twin now genuinely covers the city — every neighborhood, informal settlements included, streamed fast. The institutional half — live data, real queries, the X-Road-shaped work — remains the actual mountain, unchanged. But the foundation under the visible half is real now in a way it wasn't a week ago: real footprints, real provenance, honest heights, and an architecture that can carry whatever layer comes next — water, transit, flood risk — without re-plumbing.
The billboard is still $1.99. It's still a joke. It now sits on a map of one and a quarter million real buildings, which I'd argue makes it a better joke — and, quietly, a demo of the write-side mechanic the whole civic thesis needs. You point at a real place, you say what should be there, and the model changes. This week that's a billboard. The version worth years of work is a water ticket. Same mechanic. We're practicing.