Files
maptool/docs/nps-resources.adoc
T
randy bc505436c1
CI / check (push) Successful in 41s
CI / deploy (push) Successful in 16s
Document all NPS mapping resources investigated this session
A reference doc (docs/nps-resources.adoc) covering everything looked at
while pulling icons/controls/theme colors from NPS's mapping ecosystem:
what's actually in use (symbol-library, home-button, the Park Tiles-inspired
offline palette), what was considered and deliberately skipped (svg-icons,
markdown-handlebars, the unmerged overview/carto/wms branches) and why, the
Park Tiles cartography research (Harpers Ferry Center lineage, the four
style variants, why the actual tile service is off-limits via Mapbox
Atlas licensing, the public style JSON and Mapbox Studio style IDs found),
and the still-open upstream PR revising artwork for three icons we use.

Worth having as a knowledge base rather than re-deriving any of this from
scratch next time — NPS's tooling has repeatedly turned out to be a better
source than building something from nothing.
2026-09-07 20:07:27 +02:00

251 lines
10 KiB
Plaintext

= 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 <<park-tiles>> 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 <<park-tiles>>).