Night Trains
A scroll-driven story of Europe's sleeper-train network from 1995 to 2025. Thirty-nine routes, cross-referenced against operator archives and rail-industry press.
- Role
- Solo · research + build
- Year
- 2026
- Category
- Interactive
- Weight
- 260g
- Price
- Single-origin
- Roast
- 4/5
- Notes
- Cartographic · Scrolly · Sourced
- Stack
- Astro · Svelte · D3 · TopoJSON
The origin
ÖBB launched the Berlin–Paris Nightjet in late 2023, eight years after Deutsche Bahn ended the route. That single fact carries a longer story: a peak in the 90s, a network dismantled by budget aviation, then a fragmented revival from 2016 onward. I wanted to tell it as a map: amber lines lighting up, fading to crimson, then lighting up again. Five scroll beats, one dataset, one continent.
The pull
Astro provides the shell, with a single Svelte island for the scrollytelling. D3 draws routes onto a Natural Earth map. Routes animate in with SVG stroke-dashoffset, fade to crimson when discontinued, and return to amber on revival. The hard part was not rendering; it was the data. The seed dataset had errors: Moscow–Nice listed as 1936 instead of around 2010, CityNightLine's end year off by two years, and several unsourced totals. I completed a verification pass first — every row cross-referenced against operator archives, the International Railway Journal, and Railway Gazette — before writing a line of visualization code. The dataset moved from 40 routes to 39. sources.json ships in /data/ so anyone can audit the work.
What came out
39 verified routes · 5 narrative beats · sources.json shipped