diff --git a/README.adoc b/README.adoc index 545bb11..1055452 100644 --- a/README.adoc +++ b/README.adoc @@ -34,3 +34,4 @@ Then open http://127.0.0.1:4567 in a browser. * link:docs/architecture.adoc[Architecture] * link:docs/development.adoc[Development guide] * link:docs/third-party-notices.adoc[Third-party notices] +* link:docs/nps-resources.adoc[National Park Service mapping resources] diff --git a/docs/nps-resources.adoc b/docs/nps-resources.adoc new file mode 100644 index 0000000..4e7fef0 --- /dev/null +++ b/docs/nps-resources.adoc @@ -0,0 +1,250 @@ += National Park Service mapping resources +:toc: +:toclevels: 2 + +A reference for what's out there in the National Park Service's mapping +ecosystem: what this app has actually adopted, what was investigated and +deliberately skipped, and the licensing/provenance details behind each. +Kept as a knowledge base since NPS's tooling has repeatedly turned out to +be a better source than reinventing something from scratch — worth +checking here before searching from zero next time. + +== What this app actually uses + +[cols="1,2,1"] +|=== +| What | Where | License + +| `symbol-library` (map category icons, POI badge glyphs) +| `public/js/icons.js`'s `POI_ICONS`/`PARK4NIGHT_TAGS` +| CC0 (public domain) + +| `home-button` (the "Home" map control) +| `public/vendor/npmap-home-button/` +| MIT (per `package.json`); the whole `npmap5-plugins` repo is separately + public domain as a US government work + +| Park Tiles color palette (offline basemap theme) +| `public/js/map.js`'s `OFFLINE_THEME` +| Colors only — see <> for why the actual tile service isn't used +|=== + +See `docs/third-party-notices.adoc` for the formal vendored-library +notice and `docs/architecture.adoc` for how each is wired in. + +== npmap5-plugins + +https://github.com/nationalparkservice/npmap5-plugins — a monorepo of +MapLibre GL JS plugins built for NPS's current (v5) map stack. Live +demos: https://nationalparkservice.github.io/npmap5-plugins. More +examples/screenshots: issue +https://github.com/nationalparkservice/npmap5-plugins/issues/7[#7]. + +=== On `main` (stable, what we've pulled from) + +[cols="1,3"] +|=== +| Plugin | What it is + +| `symbol-library` +| The icon set — see above. Confirmed by the maintainer + (issue https://github.com/nationalparkservice/npmap5-plugins/issues/4[#4]) + to be the designated replacement for the older standalone + `nationalparkservice/symbol-library` repo, with a much larger + vocabulary (300+ icons vs. the ~200 in the old repo). + +| `home-button` +| Adopted, see above. + +| `svg-icons` +| *Considered, not adopted.* Solves the same "recolor an icon at + render time" problem we hit and fixed ourselves this session (see + `docs/architecture.adoc`'s note on `_registerCategoryGlyphs` — SDF + images need an actual distance field, not a plain antialiased + raster, or edges blur). Its approach is more general (lazy, + on-demand recoloring via a `styleimagemissing` listener and a + query-string-encoded `icon-image` id, vs. our upfront + per-distinct-color registration) but swapping in ~800 lines of + unfamiliar third-party logic for something already working and + understood wasn't a clear win — no bug it would fix, no capability + we're missing. + +| `interactivity` +| Not investigated in depth — "makes interactivity easier with + MapLibre GL JS". Our own click/hover handling (`gpx.js`) is already + small and specific to this app's needs. + +| `maplibre-gl-vector-text-protocol` +| Loads KML/GPX/TopoJSON/OSM directly into MapLibre client-side. Not + a fit: our GPX/FIT handling is server-side + (`lib/maptool/gpx.rb`/`fit.rb`) specifically so we can compute + track stats, POI category styling, clustering, etc. — a generic + client-side loader wouldn't give us any of that. + +| `markdown-handlebars` +| *Considered, not adopted.* Renders Markdown-with-`{{handlebars}}` + as HTML. Our waypoint popup content isn't Markdown — it's + park4night's own semi-structured text format (`formatDescription` + in `gpx.js` parses `Label: value` lines and turns Services/ + Activities into icon tags) — a generic templater would replace the + wrong layer of that logic, and would mean trusting a new, + unaudited HTML-rendering path for untrusted (uploaded-file) content + in place of our already-reviewed escaping. + +| `source-arcgis-rest`, `source-wms` +| Add ArcGIS REST / WMS raster layers as MapLibre sources. No current + need — we don't have an ArcGIS or WMS data source to point at. `wms` + explicitly noted by the user as maybe useful in the future. +|=== + +=== On unmerged feature branches (less vetted — not on `main` yet) + +[cols="1,3"] +|=== +| Plugin | What it is + +| `overview` (branch `maplibre-gl-overview`) +| A minimap/inset control, any corner, respects pitch/bearing. Live + demo: https://raw.githack.com/nationalparkservice/npmap5-plugins/maplibre-gl-overview/examples/index.html. + Note: MapLibre GL JS has no first-party minimap of its own — this + wouldn't be more "official" than any other third-party minimap + plugin, just NPS-flavored. No minimap has been requested for this + app; would be a nice-to-have, not a fix for anything. + +| `carto` (branch `maplibre-gl-carto-source`) +| Adds a vector-tile source backed by Carto.com-hosted data. Only + useful if we actually have a Carto-hosted dataset to point at — we + don't right now. + +| `wms` (branch `maplibre-gl-wms-source`) +| WMS raster layer source. Noted by the user as possibly handy later; + no current use case. +|=== + +=== Pending upstream: symbol artwork revisions + +https://github.com/nationalparkservice/symbol-library/pull/226 ("npmap-hfc +standardization 2024") — a large (169-file), still-*open*/unmerged artwork +revision pass on the *old* standalone repo, open since January 2024. Of the +icons this app actually uses, three have revised artwork proposed there: + +* `bicycle-trail` (our `sport_cycling`/`vtt`) +* `campground` (our `tourism_camp_site`) +* `pets-on-leash` (our `animaux`) + +Plus filename-only renames (e.g. `motor-bike-trail` → `motorbike-trail`, +`sea-plane` → `seaplane`) and a handful of new icons not relevant to our +current `PARK4NIGHT_TAGS` mapping (`e-bike`, `foraging-gathering`, +`seaplane`, `toilet`, `windmill`). Deliberately *not* pulled in — it's an +unmerged draft, could still change. Worth revisiting once it lands on +`main` in whichever repo ends up canonical. + +[[park-tiles]] +== Park Tiles (the NPS basemap theme) + +https://www.nps.gov/maps/web/tools/park-tiles/ — the data and cartography +system behind NPS's own web maps. Documentation: +https://www.nps.gov/maps/web/tools/npmapjs/index.html (the wider NPMap +code library docs), legend: +https://www.nps.gov/maps/web/tools/park-tiles/legend/index.html, symbols: +https://www.nps.gov/maps/web/tools/park-tiles/pictographic-symbols/index.html. + +=== Design lineage + +Explicitly traces back to the National Park Service's iconic print +brochure maps produced at the Harpers Ferry Center — the Park Tiles team +consulted HFC cartographers directly, adapting the same visual language +for digital display. This is also the design lineage behind the +`Unigrid` system (Massimo Vignelli's 1970s NPS brochure/signage +template), one of the most respected government design programs. + +=== The four style variants + +* *Standard* — the default; used in the NPS mobile app and most of + nps.gov. +* *Aerial* — integrates an imagery underlay. +* *Slate* — dark grey, lets overlay data stand out; also deliberately + chosen to work well for low-vision users with inverted browser color + settings. +* *Light* — another neutral choice for data-overlay contexts. + +=== Why we can't use the actual tile service + +Their basemap data pipeline blends NPS's own enterprise GIS data +(roads/trails/buildings/parking/POIs/boundaries) with USGS/Census federal +data and, for context outside park boundaries (streets, coastlines, +buildings, terrain/hillshade), **OpenStreetMap data pre-processed by +Mapbox as part of their commercial Atlas service** — a paid, +non-sublicensable data license scoped to NPS's own use. Separately, the +cartography is explicitly designed for park visitors (trailhead/park-unit +labeling prioritized), not general-purpose worldwide mapping. Both are +why this app uses OpenFreeMap Liberty as its actual basemap, not Park +Tiles — see `docs/architecture.adoc`'s "Offline maps" section. + +Recreating the *color choices* is a different matter — not the kind of +thing a data license restricts — and is what `OFFLINE_THEME` in +`public/js/map.js` actually does (see `docs/architecture.adoc`). + +=== Public style JSON (source for the real colors we did pull) + +Of Park Tiles' four variants, only *Imagery* is served from a plain, +unauthenticated URL: + + https://www.nps.gov/lib/npmap.js/style/ck72fwp2642dv07o7tbqinvz4.json + +("Park Tiles 4 Imagery", 129 layers — a genuine Mapbox/MapLibre style +spec, found via `npmap.js`'s own bundled `baselayers.json` config.) +*Standard*, *Slate*, and *Light* resolve through Mapbox Studio's private +Styles API using an access token instead (`style_id`s below) — visible in +`npmap.js`'s own bundle, but not something to fetch using someone else's +embedded credentials, even when technically reachable: + +[cols="1,1"] +|=== +| Variant | Mapbox Studio `style_id` + +| Standard +| `ck58pyquo009v01p99xebegr9` + +| Slate +| `ck5cpvc2e0avf01p9zaw4co8o` + +| Light +| `ck5cpia2u0auf01p9vbugvcpv` +|=== + +Colors actually pulled from the Imagery style JSON and used in +`OFFLINE_THEME`: background (`hsl(40, 37%, 97%)`, a warm cream), the +park/protected-area green (`#b3e378`), the two road-importance tiers +(`#fdefbe`/`#fef7dd`), and the park-boundary line color (`#546619`, dark +olive). The rest of `OFFLINE_THEME` extends that same warm/olive family +by eye rather than from a sourced value. + +=== Legend / cartographic hierarchy + +The legend page documents NPS's own road/trail classification standard +(primary/secondary/local/4WD/private/service roads; conventional/paved/ +boardwalk trails; public/private buildings), each shown across all four +variants. Keyed to NPS's internal "NPS geospatial data standard for +roads," not OSM's `highway=*` tagging scheme — informative as design +reference, not directly portable onto our OSM-derived data without +reinterpreting the mapping ourselves. + +== NPMap4 (the older, Leaflet-based generation) + +https://www.nps.gov/lib/npmap.js/4.2.1/ — predecessor to npmap5, +Leaflet-based, MIT-licensed. Superseded but still live. Two things worth +noting from it: + +* *Geocoder control* — example: + https://www.nps.gov/lib/npmap.js/4.2.1/examples/controls/geocoder-control.html. + Config is `geocoderControl: { searchPlaces: true }`: a search box that + resolves NPS park units by name/unit code, or a street address, or + raw coordinates, and jumps the map there. The concept (type a + place/address/coordinates, jump to it) is genuinely transferable and + not NPS-specific — could be built for this app with any geocoder (e.g. + OSM's free Nominatim), independent of anything NPS. Not implemented; + noted as a candidate feature if wanted later. +* Confirmed *not* a source for basemap tiles we could use — same + `nps-parkTiles*` naming and same underlying Mapbox Atlas-licensed data + pipeline as npmap5's Park Tiles (see <>).