An interactive MapLibre GL map + timeline of every recorded bomb and shell impact on Paris and its suburbs during the First World War.
Open index.html in a browser (keep the images/ folder alongside it). The event
data is embedded in the HTML; only the basemap tiles (OpenFreeMap) and the MapLibre
library (unpkg CDN) need a network connection.
Published site — the only files GitHub Pages serves (everything the browser fetches):
| Path | What |
|---|---|
index.html |
The built visualization (event data embedded inline). |
images/ |
46 cached photographs the popups/gallery display. |
Source you edit:
| Path | What |
|---|---|
index.template.html |
The page source (HTML/CSS/JS) with /*__DATA__*/ placeholders. Edit this, not index.html. |
parse.py, fetch_insee.py, geocode.py, fetch_images.py, build_html.py |
The data pipeline (see below). |
README.md |
This file. |
Generated data — committed so the site can be rebuilt without re-fetching everything; do not hand-edit (regenerate via the scripts):
| Path | Produced by |
|---|---|
page_wikitext.json |
raw Wikipedia source (initial download) |
events.json |
parse.py |
insee.json |
fetch_insee.py |
events.geo.json |
geocode.py |
credits.json |
fetch_images.py |
Not committed (see .gitignore): __pycache__/, geo_in.csv/geo_out.csv (geocoder
scratch), .claude/, .DS_Store.
The Python scripts are a build-time pipeline that fetches from external services
(Wikipedia, the Base Adresse Nationale, geo.api.gouv.fr, Wikimedia Commons). They are
not run by the website or by the deploy workflow — run them locally only when you
want to refresh the data, then commit the regenerated index.html + images/. The
published site is pure static HTML/JS + images.
.github/workflows/deploy.yml deploys on every push to main: it stages just
index.html + images/ and publishes them via GitHub Pages (it does not run the
Python pipeline). To update the live site, rebuild locally, commit, and push.
- 820 impacts plotted, coloured by weapon type (aircraft / Zeppelin / long-range gun).
- Vector basemap (OpenFreeMap, no API key) re-tinted to a period parchment palette.
- Impacts sized by casualties; a gold ring marks those with a photograph.
- Circle size scaled by casualties.
- Paris Gun firing positions, time-linked (with the long-range-gun layer): the timeline names the active firing position as it moves over 1918 — Forest of Saint-Gobain (~113 km) → Beaumont-en-Beine (~109 km) → north of Château-Thierry (~91 km) — with a red trajectory line to Paris. "View firing area" zooms out to show all three positions at true regional scale.
- Timeline with a play button (scrub or animate through the war), in cumulative or 7-day window mode.
- Filter by weapon type; live killed/wounded stats.
- Click any impact for date, address, casualties, the original French note, and per-event source links (the contemporary newspaper article, plus the Wikipedia table).
- Photographs: events with a damage photo (or a present-day commemorative plaque) are marked with a gold ring; the popup shows the captioned image(s) — historical damage photo plus, where one exists, the modern plaque at that address — click to enlarge in a lightbox. The Sources drawer also has a Weapons & context gallery (Taube, Gotha, Pariser Kanon, shell diagram, and the historical Paris Gun shell-impact map).
- A Sources & method drawer listing the authoritative collections behind the data.
Wikipedia compiles three layers of documentation, all surfaced in the app:
- Per-event: contemporary newspapers (L'Excelsior, Le Petit Parisien) digitised on Gallica (BnF) — linked in each impact's popup where present.
- Authoritative collections: Musée de l'Armée — “Paris bombardée”, the Commission du Vieux Paris ArcGIS dossier, and Ville de Paris archives.
- Period works: Mortane's La Guerre aérienne illustrée and Rousset's La victoire (Gallica).
page_wikitext.json— raw wikitext of the French Wikipedia article, fetched via the MediaWiki API.python3 parse.py→events.json— parses the recapitulative table (date, weapon type, address, place, comment, casualties).python3 fetch_insee.py→insee.json— resolves each commune to its INSEE code and official centre via geo.api.gouv.fr (Île-de-France only, with alias handling for quartiers).python3 geocode.py→events.geo.json— geocodes addresses via the French Base Adresse Nationale bulk API. The commune is applied as a strict INSEE citycode filter (arrondissements by postcode), so a street name can never match a same-named street in another town. Each result is validated (right area + plausible street name); anything unconfirmed falls back to the commune / arrondissement centre.python3 fetch_images.py→images/+credits.json— downloads every image used (damage photos, plaques, context illustrations) from Wikimedia Commons at 1280 px, and records each one's licence + author for attribution.python3 build_html.py→index.html— embeds the data, credits and image paths.
Rebuild everything:
python3 parse.py && python3 fetch_insee.py && python3 geocode.py && python3 fetch_images.py && python3 build_html.py
Images are cached locally in images/ so the map works offline (only the basemap
tiles need a network). Licences (from Commons): ~33 public domain, a few CC0 /
"no restrictions", and several CC BY-SA (the modern plaque photos and a handful
of illustrations). The CC images carry their author + licence in the lightbox and
a short credit under the popup thumbnail; every image also links to its Commons file
page. Redistribution is permitted under these licences provided that attribution is
shown, which it is. images/ (~16 MB) ships alongside index.html.
- Casualties are parsed from free-text French notes. Totals: 285 killed, 755 wounded across the table. Many minor impacts list no casualties.
- Locations: 678 of 820 resolved to exact street addresses (geocoded within the correct commune via its INSEE code); 142 fell back to the area centre (shown with a ⚠ note in the popup) — renamed/demolished streets, intersections, and landmarks that can't be confirmed to a single point.
- The deadliest single event is correctly the Saint-Gervais church shelling (29 March 1918, 92 killed).
- Source data is as complete/accurate as the Wikipedia table; it is the most granular public list of these events.