# Milestone 2 Spec — Interactive Map **Goal:** A `/map` page shows all entries as markers on an interactive Leaflet.js map, connected by a chronological route line, with popups linking to entries. > **Superseded — written 2026-06-21. Neither the `/map` page nor Leaflet exists.** > > - **No `/map` route.** The map renders inline on the trip page via the single shared partial > `templates/partials/entry-map.html.twig` (R1, retired 2026-07-04). `CLAUDE.md` forbids > re-creating it or linking to it. > - **Leaflet + OpenStreetMap tiles → MapLibre GL JS** with a CartoDB dark-matter basemap (R4, > 2026-06-20). > - **§2.6 nav link** is gone with the page (R6). > > The *substance* of this spec survived — markers per entry, chronological route line, popups linking > to entries, bounds fitting, mobile touch handling — it all lives in `MapUtils.initEntryMap()` in > `user/themes/intotheeast/js/maplibre-utils.js`. Only the page and the library changed. > > Details: [`../../reference/superseded-decisions.md`](../../reference/superseded-decisions.md). --- ## User Stories - As a reader, I want to see a world map showing where Mischa has been so I can understand the journey at a glance without reading every entry. - As a reader, I want to click a map marker and see the entry date, title, and a thumbnail — and be able to click through to the full entry. - As a reader on mobile, I want to pan and pinch-zoom the map with my fingers without the page scrolling underneath. - As a traveler (Mischa), I want the map to automatically include every entry that has lat/lng data — I should not need to do any manual map maintenance. - As a reader, I want the map to show the route line connecting stops in the order they were visited, so the journey makes narrative sense. --- ## Feature Details ### 2.1 — Map Page **Route:** `/map` **Template:** `map.html.twig` — extends `partials/base.html.twig` **Page file:** `user/pages/03.map/map.md` **Content:** - Full-viewport-height map container below the site header - Leaflet.js loaded from CDN (jsDelivr): `https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js` - Leaflet CSS from same CDN - Tile layer: OpenStreetMap (free, no API key): `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png` - Attribution: "© OpenStreetMap contributors" **Map initialization:** - Default zoom: auto-fit to bounds of all markers (use `map.fitBounds()`) - If no entries with GPS data: show world view, zoom 2, centered at 0,0 with a message "No locations yet" - Min zoom: 2, Max zoom: 18 --- ### 2.2 — Entry Data Serialization **How entries reach the map JS:** In `map.html.twig`, Grav's Twig will iterate all published entries under `/tracker` and serialize them to a JSON array embedded in a `