Skip to content

Add nationwide OSM bike trails layer#87

Merged
kwiens merged 8 commits into
mainfrom
feat/osm-nationwide-trails
Jun 21, 2026
Merged

Add nationwide OSM bike trails layer#87
kwiens merged 8 commits into
mainfrom
feat/osm-nationwide-trails

Conversation

@kwiens

@kwiens kwiens commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a toggleable nationwide bike-trails layer sourced from the OpenStreetMap US tile service, exposed as a "Nationwide trails" switch in the MTB tab. Separate from the curated Chattanooga MTB/route layers and off by default.

How it works

  • src/data/osm-trails.ts — source/layer IDs + the TileJSON URL (tiles.openstreetmap.us/vector/trails.json).
  • ensureOsmTrailsSource() / setOsmTrailsVisible() in utils/map.ts — attach the tileset at runtime (it is not in the Mapbox Studio style, same pattern as the MTB tileset) with a white casing for legibility. Passing the TileJSON URL gets zoom bounds (z0–14) and the "© OpenStreetMap contributors" attribution for free.
  • OSM_BIKE_TRAIL_FILTER selects bike-relevant ways: bicycle ∈ {yes, designated, permissive}, OR a present mtb:scale tag, OR highway=cycleway. Lines are colored by mtb:scale difficulty.
  • MapLegend (MTB tab) renders the "Nationwide trails" toggle, dispatching layer-toggle with layer: 'osmTrails'; Map.tsx flips visibility. Independent of the radio-button marker layers.

Verification

  • pnpm lint clean; 330 unit tests pass (added coverage for the filter shape, idempotent attach, visibility toggle, and the toggle's placement + event in the MTB tab).
  • In-browser: confirmed the source attaches, hidden by default, toggles via the real event path, and renders real OSM data — 29 features in Chattanooga, 1,233 in Bentonville AR (Slaughter Pen / Coler / Handcut Hollow MTB networks with mtb:scale, plus greenways).

Follow-up (not in this PR)

Trail POIs (parking/water/shelters from the trail_poi layer) and spreet-generated sprite icons.

@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bikemap Ready Ready Preview Jun 21, 2026 4:49pm

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee1bdb1854

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/Map.tsx
Comment thread src/utils/map.ts Outdated
Add scripts/osm_trail_elevation.py: a generalized, bbox-driven batch tool that
precomputes length + elevation for nationwide OSM bike trails. Geometry comes
from the Overpass API (full-resolution ways + OSM ids matching the tileset),
elevation from Mapbox Terrain-RGB at z14 run through a Python port of
computeElevation so values match the client. Output is sharded per region
(public/data/osm-elevation/<region>.json) with an accumulating manifest; a
built-in US state bbox table supports the eventual nationwide run. Both the
Overpass cell fetches and per-way terrain sampling are thread-pooled (--workers,
default 3) with a thread-safe terrain-tile cache.

Generate Oregon data (63,670 ways).

Client: lookupPrecomputedElevation loads the manifest + the region file covering
a clicked point; the OSM trail popup renders precomputed length/elevation (and
the elevation profile) instantly, falling back to on-demand terrain sampling on
a miss.
Selecting an OSM trail now highlights it + opens the elevation pane (committed in
58d4f43); the old click popup is gone, so drop the now-unused popup renderer and
its helpers: buildOsmTrailPopupHTML + osmTrailType/Difficulty/DetailRows and the
OsmTrailMetrics formatting (osm-trails.ts), the osm-trail-* popup CSS (map.css),
and traceLengthMeters/sampleTrailElevation (osm-elevation.ts), plus their tests.
Keep the shared MTB_SCALE_RATING (feeds the line color) and the terrain sampler.
Update CLAUDE.md to describe pane-only selection + the precompute→pane stats.
- Register the OSM hit-layer click handler after the curated route + MTB hit
  handlers, so where an OSM way overlaps a curated trail the curated handler
  preventDefault()s first and the trail stays selectable.
- Clear the OSM highlight + elevation pane when the Nationwide trails layer is
  toggled off (guarded on an active OSM selection so a curated trail's pane is
  left untouched).
- registerOsmTrailSelection now returns a cleanup that removes its window
  listeners; Map.tsx runs it on teardown/restyle so remounts don't leak or
  duplicate listeners (or call clearOsmTrailHighlight on a removed map).
Selecting an OSM trail now shows a focused detail row beneath the pane header —
type · surface · bikes (and difficulty when mtb:scale is present) plus a small
'OSM ↗' link to openstreetmap.org. Details are derived from the feature's OSM
tags (osmTrailDetails in osm-trails.ts) and travel on the ElevationProfile as an
optional 'osm' field, so they clear automatically when the selection changes.
Curated trails and rides leave it undefined.
kwiens added 2 commits June 21, 2026 09:36
Concurrent/bursty Overpass requests got the client IP temporarily blocked.
Decouple the two stages: per-way terrain sampling keeps --workers (default 3,
Mapbox tolerates concurrency), but Overpass now defaults to --overpass-workers 1
and --polite-sleep 3. Raise --overpass-workers only against a private/self-hosted
Overpass instance, never the public endpoint.
…rails

# Conflicts:
#	src/components/sidebar/ElevationProfile.tsx
#	src/data/mountain-bike-trails.ts
Add an --overpass-ssh USER@HOST option that runs Overpass queries through
`ssh host curl` (query over stdin, key auth) for when the local IP is blocked
or rate-limited; elevation still samples Mapbox locally. Used it to finish
Tennessee after our IP got blocked hitting the public endpoint too hard.

Generate complete Tennessee data: 12,657 ways across all 72 bbox cells.
@kwiens

kwiens commented Jun 21, 2026

Copy link
Copy Markdown
Owner Author

CR 👍

@kwiens
kwiens merged commit a1bf5de into main Jun 21, 2026
3 checks passed
kwiens added a commit that referenced this pull request Jun 21, 2026
Resolve map.css conflict: keep the new .rental-link styles; drop the
.osm-trail-* block, which main refactored away (PR #87) and which the
merged osm-trails popup no longer references.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant