Method
How The Century of Africa was made
The story is four chapters of maps. This is the paperwork behind them: every source and what it actually measures, the judgment calls and why they went the way they did, the things that were tried and thrown away, and how the modelled numbers hold up against independent data.
1. The question, and why four chapters
The UN expects Africa's population to roughly triple this century while every other region levels off or falls. The interesting thing about that number is not its size, it is how little of it is negotiable: it is mostly arithmetic on an age pyramid that already exists. The piece argues one thing, at four scales, because a claim that only works at one scale is not really a finding. The arithmetic is locked. The systems are not.
- The continent. Country by country to 2100, plus the mechanism. Growth is not a forecast about birth rates so much as arithmetic about people already alive: the mothers of 2050 have been born. The median-age map is there so the reader can see the momentum rather than take it on trust. This is the chapter that establishes the locked half, and it is also why the piece does not point at fertility: birth rates are falling and it will not change the 2050 number.
- The cities. The same growth expressed as places. Circles sized by population, running from 1975 to 2050 on the UN's annual series, so the reader watches the map fill rather than reading a ranking.
- The connections. Cities that size need to reach each other. This chapter asks where the demand is and whether the network meets it, and it is the first place the gap is measured rather than asserted. It is also the chapter with the most modelling in it, so it carries the most testing.
- The ground. One city, Kinshasa, at satellite resolution. The continental chapters are all projection. This one is measurement: what actually got built, where, on what slope, with how much street. It is where the gap stops being a continental abstraction and turns into metres of street per person.
The order is deliberate. Each chapter is a smaller frame than the last, and the last one is the only place the reader can check the story against something you could walk on. The argument narrows the same way: a number nobody can move, then the places it lands, then the systems that have to meet it, then one city where you can measure whether they did.
2. Every source, and what it measures
UN World Population Prospects 2024
Country population by year, medium variant, plus the low and high variants drawn as the band on the regional chart. This is an estimate built from national statistics, censuses and vital registration, projected forward under fertility and mortality assumptions. It is a central path, not a prediction, and the overtaking years the story quotes move if you change the variant.
UN World Urbanization Prospects 2025, DEGURBA cities
Agglomeration population 1975 to 2050. What it measures is a city defined by a consistent settlement rule rather than by whatever each country happens to call a municipality, which is why the figures sometimes differ from a national statistics office. The 2100 city figures are not the UN's: they come from Hoornweg and Pope (2017), sit well above any UN city horizon, and are drawn hollow everywhere they appear.
JRC Global Human Settlement Layer, R2023A
Two grids, both at 3 arcseconds, both tile R10_C20. GHS-BUILT-S gives the share of each cell covered by building surface, derived from the Landsat and Sentinel archives. GHS-POP distributes census counts across those cells. The important thing about both is that they are model output: nobody measured Kinshasa's rooftops in 1975, an algorithm inferred them from imagery. The 2030 epoch is the JRC's own projection, not an observation.
Copernicus DEM GLO-30
Ground elevation at 30 metres, from radar. Slope is derived from it here, not supplied by it. Licensed free and open, with the attribution notice the licence requires carried in the story footer.
OpenStreetMap
The river, the roads and streets, the commune boundaries, the real alignments of built railways, the Matadi corridor, and the road network the gravity model is tested against. OSM measures what mappers have mapped. In Kinshasa that is good and getting better, and it is a present-day snapshot with no history, which matters for one figure and is flagged where it does.
Harmonized DMSP and VIIRS nighttime lights, 2020
Li, Zhou, Zhao and Zhao's harmonized series, which stitches the old DMSP sensor to the newer VIIRS one so the two are comparable. It measures light leaving the ground at night. It is a proxy for electrification and activity, not a measurement of either.
World Bank Open Data
Access to electricity and to basic drinking water, as a share of population. The snapshot map is the most recent reported year per country, so it mixes observations from different years, and its "people without" totals multiply that share by the UN's 2025 population.
The chart is a different cut of the same indicators: the full series from 2000 to 2022, counting only the countries reporting in a given year and pairing each year's share against UN population for that same year. Counting a consistent set per year is what stops a country reporting late from putting a step in either curve.
Natural Earth
Country outlines and the existing rail and road layer drawn in chapter three. It is a cartographic basemap at 1:10 million, generalised for drawing. That generalisation is fine for a backdrop and, as section 4 records, not fine for measurement.
3. The decisions
A 20 per cent built threshold
GHS-BUILT-S is continuous: every cell has a built fraction between zero and one. Drawing it that way produces a soft grey smear with no edge, and the whole point of chapter four is the edge, because the reader is being shown where the city stopped in each decade. Twenty per cent is the point where the footprint reads as a city rather than as a haze, and it is applied identically to every epoch so the comparison between decades is consistent even though the absolute area depends on the cut.
Block-averaging the 30 metre DEM
The elevation model is roughly three times finer than the built-up grid. Deriving slope at 30 metres and then asking which 92 metre built cells are steep mixes two resolutions and produces detail that is not really there. The DEM is averaged down to the built grid first, so slope and built-up are answering at the same scale. This also took the polygonize step from over half an hour to about ninety seconds, and cut the layer from 1.33 MB to 0.31 MB, which is a real consideration on a page that ships its data.
Classed colour, not a gradient
The chapter 1 maps were first drawn with linear colour ramps stretched across a global range, and the result was a continent of one colour. Half of Africa's median ages fall between 15 and 22, which was a single segment of that ramp, so Niger at 15.6 and Botswana at 26 came out the same orange. The map looked like data and carried none.
They are now classed rather than interpolated, on Fisher-Jenks breaks
computed from the African values themselves, with extra classes added above
where the rest of the world needs somewhere to sit. Flat classes are easier
to compare than a gradient, and the key can name what each one means instead
of showing a bar with two numbers on it. 17_class_breaks.py
recomputes the breaks and reports how many countries land in each class, so
the choice is checkable rather than a matter of taste.
Growth keeps a hard boundary at one times, because shrinking and growing are different kinds of country rather than two ends of a scale, and the top age classes exist so that Japan at 49.8 still reads as a different world from Tunisia at 32.9. One population scale serves 2025, 2050 and 2100 rather than three fitted ones, so the reader watches countries climb between steps: four African countries are in the top class by 2100 and none are today.
Two slope classes, not five
Steep and steepest, at 10 and 15 degrees. Five classes would look more analytical and would be false precision against a 92 metre surface. Two classes is what the data can carry.
Rings measured from Gombe
The expansion analysis measures distance outward from 15.313E, 4.305S, the old river front. Kinshasa did not grow from a geometric centroid, it grew away from the river, and a centroid would have put the origin in ground that was empty in 1975. Using the historical core means the rings answer the question actually being asked: how far from the original city did each decade build?
Cumulative epoch masks, drawn newest first
Each growth ring is the full built footprint at that epoch, not just the increment. Drawing increments leaves gaps wherever the model revised a cell between epochs, and the rings stop nesting. Cumulative masks nest by construction; painting them newest first means each older, smaller footprint lands on top, and the reader sees clean vintage bands.
Why the Tokyo and New York circles came out
Chapter two originally drew Western cities as comparison circles. On a frame that has to hold the whole continent they sat at the edge of the viewport, small, and far from anything to compare against. They made the comparison harder rather than easier. The comparison is now made in the copy, as numbers, where a reader can actually hold both figures at once.
Why the 2100 circles are hollow
Every other circle on that map is a UN series. The 2100 figures are one academic team's projection, from a different method, well above the UN's own city horizons. They are worth showing and they are not the same kind of object, so they are drawn as rings rather than discs, and labelled.
Why the whole thing is GeoJSON with no backend
About 4 MB of geometry, committed, split into a critical wave and a deferred one. No tile server, no API, nothing to keep running or pay for. It loads from any static host and it will still work in five years, which is a longer guarantee than most map stacks offer.
4. Tried and rejected
The cumulative slope statistic
The slope chapter began with a hypothesis: as Kinshasa ran out of flat land it would be forced uphill. The first statistic computed for it was the share of the whole built footprint on steep ground, epoch by epoch. It moved from 20.7 per cent to 25.5 per cent across fifty years, which says almost nothing, because each epoch is dominated by the ground already built in the one before. Recomputing it per increment, on only the cells each decade added, produced the actual result: the 1975 city sits at a median 2 degrees, and every later decade came in steeper, the 1990 expansion at double the old city's slope. The copy was then rewritten to follow the number rather than the hypothesis. Both statistics were correct; only one was informative.
Natural Earth for the corridor coverage test
The obvious way to test the gravity model was against the road layer already loaded on the page. It was tried on a single link first. Natural Earth's 1:10 million network reports Lagos to Onitsha as 22 per cent served; OpenStreetMap reports 75 per cent. The generalised basemap would have produced a confidently wrong finding and there would have been nothing in the output to reveal it. The test uses OSM.
A slope layer derived to the camera's bounding box
The terrain derivation was first run over exactly the area the map shows. The layer then drew a hard rectangle across the map wherever the data simply stopped. The derivation window is now wider than the camera, which costs nothing and looks like terrain instead of like a raster.
Five decimal places of GeoJSON
Coordinates are written at three decimals, roughly 110 metres, which is finer than any layer on the page resolves. The extra digits were bytes spent to encode precision that was never in the source.
5. Validation
Everything in chapters one to three is projection or model output, and chapter four is model output too. So two independent checks were run, both as scripts in the pipeline, both writing their results to committed JSON that the page reads from.
GHS-POP against the UN, inside real boundaries
The JRC infers population from satellite imagery. The UN estimates the same cities from national statistics. Two methods with almost nothing in common, so where they agree that is evidence, and where they disagree that is worth naming.
14_validate.py sums the GHS-POP grid inside Kinshasa's 3,516
square kilometres of OpenStreetMap commune boundaries, which is close to the
footprint the UN's city figure describes, and compares the two.
| Year | GHS-POP | UN WUP | Ratio |
|---|---|---|---|
| 1975 | 1.17M | 0.98M | 1.19 |
| 2025 | 13.24M | 10.90M | 1.21 |
The grid runs about a fifth above the UN in both years. That is the useful part: the offset is stable across fifty years, so the growth the story describes is not an artefact of the grid drifting. A source that agreed in 1975 and diverged by 2025 would have undermined the whole chapter. This one does not, and the story now says on the page that its Kinshasa totals carry about that much slack.
Brazzaville was intended as a second case and could not be run: OSM has no admin_level 7 boundaries north of the Pool, so there was nothing to sum inside. It is reported here rather than quietly dropped.
The same script re-derives the density figure the story quotes. Inside the communes, the 99th percentile cell holds about 133,000 people per square kilometre and the peak is roughly 298,000, with 7,249 cells at or above 60,000. The story's "over 60,000 per square kilometre" is a conservative reading of its own data.
Share against absolute number
The story claims a problem of rate, and a snapshot cannot support a claim about rate. So the services indicators were rebuilt as series.
Both say the same thing independently. Electricity access across Africa went from 37.7% to 58.5% between 2000 and 2022 while the number of people without it rose from 510 million to 600 million. Water access went from 52.8% to 70.1% while the number without rose from 386 million to 429 million. Two indicators, separately collected, both showing real and large progress losing to the population it is chasing.
This is the difference between a piece that asserts a gap and one that measures whether the gap is closing. It is also why the copy credits the building rather than dismissing it, and why the map carries a layer for electrification gained since 2000: Kenya went from 15% to 76% and Rwanda from 6% to 51% in the same window, which is the evidence that the number is a choice and not a fate.
Drawing the corridors on land
A gravity model pairs cities. It has no opinion about what lies between them, so drawn as straight great circles, twelve of the thirty-six links ran across open water: Luanda to Lagos was 98.5 per cent Atlantic. Five of the curated Trans-African Highway lines did the same thing along the West African coast.
That was not only an ugly map. The coverage test below samples points along each link and asks whether a road passes nearby, so along an ocean line it was measuring the sea.
18_land_routes.py reroutes any line crossing water along a
land-constrained shortest path: a 0.2 degree grid over Africa, cells kept
where the Natural Earth land polygons reach, eight-way search with
great-circle edge costs, simplified afterwards at 0.08 degrees so the grid
staircase smooths without cutting corners across bays. The worst remaining
overlap with water is 3.1 per cent, which is a coastal route hugging
the shore at 22 kilometre resolution.
The scores are still calculated on straight-line distance, which is the textbook formulation and the thing the model is actually claiming. What the routing adds is the length of the trip: Lagos to Luanda is 2,046 km apart and 2,421 km by road around the Gulf, a fifth further and across five borders. Every link carries that ratio, and the corridor popups show it.
The routes are schematic. They know nothing of terrain, borders, gradient or existing pavement, and they are not engineering alignments. They promise only that a reader tracing one with a finger stays on the continent.
The gravity model against the road network
Chapter three runs population times population over distance squared
across the thirty largest African cities of 2050. That is a textbook toy,
and calling it a sketch is honest but is not a defence. So it was tested.
15_corridor_coverage.py samples 40 points along each of the 36
modelled links and asks whether a mapped motorway, trunk or primary road
passes within about 24 kilometres. It runs after the routing above, so it
measures the road beside the line that is actually drawn.
- 24 of 36 modelled links already have a primary road along at least four fifths of the route.
- The median link is 90 per cent covered.
- The model's highest-demand link, Cairo to Alexandria at a score of 9,435, six times the next, is 90 per cent served. Yaoundé to Douala, Accra to Kumasi, Lagos to Onitsha, Lagos to Owerri and Accra to Owerri all come back fully served.
A model whose strongest output is a corridor that has already been built is not drawing noise, and that is what licenses reading the rest of it. Which makes the low scores the finding rather than the failure: Dar es Salaam to Kampala at 42 per cent, Luanda to Kinshasa at 48, Cairo to Khartoum at 48, Addis Ababa to Khartoum and Kinshasa to Yaoundé at 52, Dar es Salaam to Nairobi at 62. They are interior and cross-border links, not coastal ones.
These figures replace an earlier set that was wrong. Measured along the old straight-line geometry, Luanda to Lagos came back 8 per cent served, which the story quoted as its sharpest example of unmet demand. It was an artefact of sampling the Atlantic. Along the coastal road the same link is 88 per cent served, and the honest thing about it is the detour, not the absence. The threshold moved too: the query fetched roads within 0.22 degrees while the test counted them at 0.25, so roads in that band satisfied the test but were never retrieved. Both numbers are 0.22 now.
The test measures whether a route exists, not whether it is paved, open, safe or big enough. Every Overpass response is cached under the pipeline's raw directory, keyed on the query itself so that moving a corridor cannot be answered with the roads around the line it used to follow.
One city, or a pattern?
The sharpest number in the story is Kinshasa's street supply falling from about nine metres per resident to one. On its own that is a single case, and the fair objection is that Kinshasa is exceptional: a capital that grew through state collapse and two wars.
16_city_streets.py runs the identical measurement over nine
cities, chosen to span the range rather than to flatter the argument. Cairo
and Accra are in it precisely because they were the most likely to contradict
it. Every city with a UN 1975 baseline has less street per resident today
than it had then. Kinshasa comes last at 1.18 metres against a median
of 1.82, so it is the sharp end of a real pattern rather than a
typical case, and Cairo fell least, which is what a state that builds looks
like.
Two things make that result worth trusting. Kinshasa's figure here is derived from a different window than the chapter's own, and both land on 1.18. And the check caught a real fault on the way: Addis Ababa first came back at 0.12 metres per resident, an order of magnitude below everything else, because its measurement window ran off the edge of its GHSL tile. Asking for a window past a tile edge does not fail. It returns the rows that exist while the transform still describes the window requested, so the footprint silently shifts by the missing margin. The script now mosaics every tile a window touches and refuses to run on partial coverage.
The numbers on the page are asserted, not typed
Every figure quoted in the story is checked against the shipped JSON and GeoJSON by a test script before it goes in the HTML, so the copy cannot drift away from the data during an edit. Layout, contrast, reduced-motion behaviour and small-viewport rendering are checked by an audit script driving a headless browser at several viewport sizes.
6. Known limits
- There is no ground truth here beyond the cross-checks above. Nobody surveyed Kinshasa for this. Two models agreeing is evidence, not proof.
- OSM has no history. Street length per resident counts today's network inside each epoch's built footprint, so the early decades are credited with streets that may not have existed. The real fall from nine metres per person to one is steeper than the chart shows, not shallower.
- The 2030 built-up epoch is a projection by the JRC, and it adds a small area, so statistics computed on that increment alone move around more than the earlier ones.
- The gravity model is still a demand sketch, even after the coverage test. It knows populations and distances. It does not know terrain, borders, tariffs, gauge, politics or money.
- Corridor geometry is schematic city to city, except the built railways, which use their real OSM alignments.
- The projections belong to the UN and the cited authors, not to this site. The medium variant is a central path. Change the variant and the crossover years move.