diff --git a/openspec/changes/osm-overlays/.openspec.yaml b/openspec/changes/archive/2026-04-11-osm-overlays/.openspec.yaml similarity index 100% rename from openspec/changes/osm-overlays/.openspec.yaml rename to openspec/changes/archive/2026-04-11-osm-overlays/.openspec.yaml diff --git a/openspec/changes/osm-overlays/design.md b/openspec/changes/archive/2026-04-11-osm-overlays/design.md similarity index 100% rename from openspec/changes/osm-overlays/design.md rename to openspec/changes/archive/2026-04-11-osm-overlays/design.md diff --git a/openspec/changes/osm-overlays/proposal.md b/openspec/changes/archive/2026-04-11-osm-overlays/proposal.md similarity index 100% rename from openspec/changes/osm-overlays/proposal.md rename to openspec/changes/archive/2026-04-11-osm-overlays/proposal.md diff --git a/openspec/changes/osm-overlays/specs/map-display/spec.md b/openspec/changes/archive/2026-04-11-osm-overlays/specs/map-display/spec.md similarity index 100% rename from openspec/changes/osm-overlays/specs/map-display/spec.md rename to openspec/changes/archive/2026-04-11-osm-overlays/specs/map-display/spec.md diff --git a/openspec/changes/osm-overlays/specs/osm-poi-overlays/spec.md b/openspec/changes/archive/2026-04-11-osm-overlays/specs/osm-poi-overlays/spec.md similarity index 100% rename from openspec/changes/osm-overlays/specs/osm-poi-overlays/spec.md rename to openspec/changes/archive/2026-04-11-osm-overlays/specs/osm-poi-overlays/spec.md diff --git a/openspec/changes/osm-overlays/specs/osm-tile-overlays/spec.md b/openspec/changes/archive/2026-04-11-osm-overlays/specs/osm-tile-overlays/spec.md similarity index 100% rename from openspec/changes/osm-overlays/specs/osm-tile-overlays/spec.md rename to openspec/changes/archive/2026-04-11-osm-overlays/specs/osm-tile-overlays/spec.md diff --git a/openspec/changes/osm-overlays/specs/planner-session/spec.md b/openspec/changes/archive/2026-04-11-osm-overlays/specs/planner-session/spec.md similarity index 100% rename from openspec/changes/osm-overlays/specs/planner-session/spec.md rename to openspec/changes/archive/2026-04-11-osm-overlays/specs/planner-session/spec.md diff --git a/openspec/changes/osm-overlays/tasks.md b/openspec/changes/archive/2026-04-11-osm-overlays/tasks.md similarity index 100% rename from openspec/changes/osm-overlays/tasks.md rename to openspec/changes/archive/2026-04-11-osm-overlays/tasks.md diff --git a/openspec/specs/map-display/spec.md b/openspec/specs/map-display/spec.md index bdbb97e..50d474f 100644 --- a/openspec/specs/map-display/spec.md +++ b/openspec/specs/map-display/spec.md @@ -1,18 +1,7 @@ -## Purpose - -Interactive map rendering with Leaflet and OSM tiles, waypoint editing, route visualization, elevation profiles, multiplayer cursors, and polygon drawing for both Planner and Journal apps. - -## Requirements - -### Requirement: Map rendering with OSM tiles -The Planner and Journal SHALL render interactive maps using Leaflet with OpenStreetMap tiles as the default base layer. - -#### Scenario: Default map view -- **WHEN** a user opens the Planner or a route view in the Journal -- **THEN** an interactive map is displayed with OpenStreetMap tiles centered on the route or a default location (Germany) +## MODIFIED Requirements ### Requirement: Base layer switching -The map SHALL support switching between multiple base tile layers. +The map SHALL support switching between multiple base tile layers, and SHALL support toggling overlay tile layers independently. #### Scenario: Switch to OpenTopoMap - **WHEN** a user selects "OpenTopoMap" from the layer switcher @@ -22,80 +11,10 @@ The map SHALL support switching between multiple base tile layers. - **WHEN** a user opens the layer switcher - **THEN** the options include OpenStreetMap, OpenTopoMap, and CyclOSM -### Requirement: Waypoint editing on map -The Planner map SHALL allow users to add, move, and delete waypoints by interacting with the map. +#### Scenario: Available overlay layers +- **WHEN** a user opens the layer switcher +- **THEN** overlay checkboxes are shown for Hillshading, Cycling Routes, Hiking Routes, and MTB Routes -#### Scenario: Add waypoint by clicking -- **WHEN** a user clicks on the map -- **THEN** a new waypoint is added at the clicked location and synced via Yjs - -#### Scenario: Move waypoint by dragging -- **WHEN** a user drags an existing waypoint marker -- **THEN** the waypoint coordinates update and sync via Yjs - -#### Scenario: Delete waypoint -- **WHEN** a user right-clicks a waypoint and selects "Delete" -- **THEN** the waypoint is removed and the change syncs via Yjs - -### Requirement: Route visualization -The map SHALL display the computed route as an interactive, optionally color-coded polyline on the map. - -#### Scenario: Display route -- **WHEN** BRouter returns a route GeoJSON -- **THEN** the route is rendered as a polyline on the map, colored according to the active color mode - -#### Scenario: Route updates on waypoint change -- **WHEN** a waypoint is added, moved, or deleted -- **THEN** the route polyline updates after BRouter recomputes the route - -#### Scenario: Ghost marker on hover -- **WHEN** the cursor is within 15 pixels of the route polyline -- **THEN** a transient ghost marker appears at the nearest route point, which can be clicked or dragged to insert a waypoint (see route-splitting and route-drag-reshape specs) - -### Requirement: Elevation profile display -The Planner SHALL display an elevation profile chart for the current route. - -#### Scenario: Show elevation profile -- **WHEN** a route is computed -- **THEN** an elevation profile chart is displayed below the map showing distance vs elevation with total ascent/descent statistics - -### Requirement: Planner home page -The Planner home page SHALL provide a clear call-to-action to create a new planning session and a link back to the home page from within sessions. - -#### Scenario: Home page CTA -- **WHEN** a user visits the Planner home page -- **THEN** a prominent "Start Planning" button is visible that links to `/new` - -#### Scenario: Session home link -- **WHEN** a user is in a planning session -- **THEN** the header contains a link back to the Planner home page - -### Requirement: Map cursor rendering -Other participants' cursors on the map SHALL be clearly visible with proper styling. - -#### Scenario: Cursor appearance -- **WHEN** another participant moves their mouse on the map -- **THEN** a colored pointer icon with their name tag appears at the cursor position - -#### Scenario: Cursor does not obscure map controls -- **WHEN** cursors are rendered -- **THEN** they appear below map controls (zoom, layer switcher) in z-index - -### Requirement: Map components used in journal app -The `@trails-cool/map` package's `MapView` and `RouteLayer` components SHALL be used in the journal app for route previews, in addition to the planner. - -#### Scenario: Journal uses shared map components -- **WHEN** the journal renders a route map preview or detail map -- **THEN** it uses `MapView` and `RouteLayer` from `@trails-cool/map` -- **AND** no map code is duplicated between planner and journal - -### Requirement: Map polygon drawing -The Planner map SHALL support drawing and displaying no-go area polygons. - -#### Scenario: Polygon tool -- **WHEN** a user activates the no-go area tool -- **THEN** they can draw a polygon by clicking points on the map - -#### Scenario: Polygon display -- **WHEN** no-go areas exist in the session -- **THEN** they are rendered as semi-transparent red polygons on the map +#### Scenario: Toggle overlay +- **WHEN** a user checks an overlay checkbox in the layer switcher +- **THEN** the overlay tiles are rendered on top of the current base layer diff --git a/openspec/specs/osm-poi-overlays/spec.md b/openspec/specs/osm-poi-overlays/spec.md new file mode 100644 index 0000000..f05a44b --- /dev/null +++ b/openspec/specs/osm-poi-overlays/spec.md @@ -0,0 +1,83 @@ +## ADDED Requirements + +### Requirement: POI overlay panel +The Planner SHALL provide a collapsible panel for toggling POI categories on the map. + +#### Scenario: Open POI panel +- **WHEN** a user clicks the POI toggle button on the map +- **THEN** a panel opens showing checkboxes for each POI category with icons and names + +#### Scenario: Close POI panel +- **WHEN** the POI panel is open and the user clicks the toggle button again +- **THEN** the panel collapses and POI markers remain visible on the map + +### Requirement: POI categories +The Planner SHALL support the following POI categories queried from OpenStreetMap via Overpass API: drinking water, shelter, camping, food & drink, groceries, bike infrastructure, accommodation, viewpoints, and toilets. + +#### Scenario: Enable a POI category +- **WHEN** a user enables the "Drinking water" category in the POI panel +- **THEN** drinking water POIs within the current map viewport are fetched from Overpass and rendered as markers + +#### Scenario: Disable a POI category +- **WHEN** a user disables a previously enabled POI category +- **THEN** markers for that category are removed from the map + +#### Scenario: Multiple categories enabled +- **WHEN** a user enables "Camping" and "Drinking water" simultaneously +- **THEN** both categories of markers are visible, each with distinct icons + +### Requirement: POI markers +Each POI SHALL be rendered as a map marker with a category-specific icon. + +#### Scenario: POI marker display +- **WHEN** POIs are loaded for an enabled category +- **THEN** each POI appears as a small icon marker at its coordinates on the map + +#### Scenario: POI marker popup +- **WHEN** a user clicks a POI marker +- **THEN** a popup shows the POI name, category, and available details (opening hours, website, OSM link) + +#### Scenario: POI marker clustering +- **WHEN** many POIs are visible in a small area +- **THEN** markers are clustered with a count badge, and expand when the user zooms in + +### Requirement: Viewport-scoped POI loading +The Planner SHALL load POIs only within the current map viewport, refreshing when the viewport changes. + +#### Scenario: Load POIs on viewport +- **WHEN** POI categories are enabled and the user pans or zooms the map +- **THEN** POIs are fetched for the new viewport after a 500ms debounce + +#### Scenario: Zoom threshold +- **WHEN** the map zoom level is below 12 +- **THEN** POI queries are not sent and a message indicates the user should zoom in to see POIs + +#### Scenario: Cached results +- **WHEN** the user pans back to a previously viewed area within 10 minutes +- **THEN** cached POI results are displayed without a new Overpass query + +### Requirement: Overpass rate limit handling +The Planner SHALL handle Overpass API rate limits gracefully. + +#### Scenario: Rate limited response +- **WHEN** the Overpass API returns a 429 status +- **THEN** the Planner shows a temporary "POI data unavailable — try again shortly" message and retries with exponential backoff + +#### Scenario: Overpass unavailable +- **WHEN** the Overpass API is unreachable +- **THEN** the Planner shows a message and tile overlays continue to function normally + +### Requirement: Profile-aware POI defaults +The Planner SHALL auto-enable relevant POI categories when the routing profile changes. + +#### Scenario: Cycling profile POI defaults +- **WHEN** the routing profile is changed to a cycling variant +- **THEN** the "Bike infrastructure" POI category is automatically enabled + +#### Scenario: Hiking profile POI defaults +- **WHEN** the routing profile is changed to a hiking variant +- **THEN** "Shelter" and "Viewpoints" POI categories are automatically enabled + +#### Scenario: User override persists +- **WHEN** a user manually disables an auto-enabled POI category +- **THEN** it remains disabled until the next profile change diff --git a/openspec/specs/osm-tile-overlays/spec.md b/openspec/specs/osm-tile-overlays/spec.md new file mode 100644 index 0000000..396fee5 --- /dev/null +++ b/openspec/specs/osm-tile-overlays/spec.md @@ -0,0 +1,68 @@ +## ADDED Requirements + +### Requirement: Hillshading overlay +The Planner map SHALL offer a hillshading tile overlay that visualizes terrain relief. + +#### Scenario: Enable hillshading +- **WHEN** a user toggles "Hillshading" in the layer switcher +- **THEN** semi-transparent terrain shading tiles are rendered on top of the base layer + +#### Scenario: Hillshading with any base layer +- **WHEN** hillshading is enabled and the user switches base layers +- **THEN** hillshading remains visible on top of the new base layer + +### Requirement: Waymarked Trails cycling overlay +The Planner map SHALL offer a Waymarked Trails cycling overlay showing official cycle route networks. + +#### Scenario: Enable cycling routes overlay +- **WHEN** a user toggles "Cycling Routes" in the layer switcher +- **THEN** official cycling routes (EuroVelo, national networks) are rendered as colored lines on the map from Waymarked Trails tiles + +#### Scenario: Cycling overlay at different zoom levels +- **WHEN** cycling routes overlay is enabled +- **THEN** international routes are visible at low zoom and local routes appear at higher zoom levels + +### Requirement: Waymarked Trails hiking overlay +The Planner map SHALL offer a Waymarked Trails hiking overlay showing official hiking trail networks. + +#### Scenario: Enable hiking routes overlay +- **WHEN** a user toggles "Hiking Routes" in the layer switcher +- **THEN** official hiking trails (GR routes, national trails) are rendered as colored lines on the map + +### Requirement: Waymarked Trails MTB overlay +The Planner map SHALL offer a Waymarked Trails MTB overlay showing official mountain bike trail networks. + +#### Scenario: Enable MTB routes overlay +- **WHEN** a user toggles "MTB Routes" in the layer switcher +- **THEN** official MTB trails are rendered as colored lines on the map + +### Requirement: Multiple simultaneous overlays +The Planner map SHALL support enabling multiple tile overlays at the same time. + +#### Scenario: Hillshading plus cycling routes +- **WHEN** a user enables both "Hillshading" and "Cycling Routes" +- **THEN** both overlays are visible simultaneously, with cycling routes rendered above hillshading + +### Requirement: Overlay tile attribution +Each tile overlay SHALL display proper attribution when enabled. + +#### Scenario: Attribution updates +- **WHEN** an overlay is toggled on +- **THEN** its attribution text is added to the map attribution control +- **WHEN** the overlay is toggled off +- **THEN** its attribution text is removed + +### Requirement: Profile-aware overlay suggestions +The Planner SHALL auto-enable relevant tile overlays when the routing profile changes. + +#### Scenario: Switch to cycling profile +- **WHEN** the routing profile is changed to a cycling variant +- **THEN** the Waymarked Trails cycling overlay is automatically enabled + +#### Scenario: Switch to hiking profile +- **WHEN** the routing profile is changed to a hiking variant +- **THEN** the Waymarked Trails hiking overlay is automatically enabled + +#### Scenario: User can disable auto-enabled overlays +- **WHEN** an overlay was auto-enabled by a profile change +- **THEN** the user can manually disable it and it stays disabled until the next profile change diff --git a/openspec/specs/planner-session/spec.md b/openspec/specs/planner-session/spec.md index e839e41..7233678 100644 --- a/openspec/specs/planner-session/spec.md +++ b/openspec/specs/planner-session/spec.md @@ -1,13 +1,24 @@ -## Purpose +## MODIFIED Requirements -Collaborative planning session management with Yjs CRDT synchronization, supporting initialization from URL parameters, journal handoff, and GPX file upload. +### Requirement: Real-time collaborative editing +The Planner SHALL synchronize waypoint edits, route options, and overlay preferences across all connected participants in real-time using Yjs CRDTs. -## Requirements +#### Scenario: Add waypoint +- **WHEN** participant A adds a waypoint to the map +- **THEN** participant B sees the waypoint appear within 500ms -### Requirement: Session initialization from GPX -The Planner SHALL support initializing sessions from a GPX file upload in addition to URL parameters and the journal handoff. +#### Scenario: Reorder waypoints +- **WHEN** participant A drags a waypoint to reorder it +- **THEN** participant B sees the updated waypoint order within 500ms -#### Scenario: Session created from GPX upload -- **WHEN** a session is created via GPX file upload on the home page -- **THEN** waypoints and no-go areas from the GPX are passed via URL parameters to the session page -- **AND** the Yjs document is initialized with the extracted data on the client side +#### Scenario: Concurrent edits +- **WHEN** participant A and B both add waypoints simultaneously +- **THEN** both waypoints appear for both participants without conflict + +#### Scenario: Overlay sync +- **WHEN** participant A enables the "Hillshading" tile overlay +- **THEN** participant B sees hillshading appear on their map within 500ms + +#### Scenario: POI category sync +- **WHEN** participant A enables the "Drinking water" POI category +- **THEN** participant B sees drinking water markers appear on their map