doxa-maps/library
Doxa Maps 3b5a86aaef Auto resolves to MapLibre; a token no longer picks the engine
The Driver wants MapLibre as the default everywhere, on cost and on how it
looks, with Mapbox supported as an explicit choice.

One line decided it. resolveMapProvider read
  explicit || (token present ? 'mapbox' : 'maplibre')
so merely HOLDING a Mapbox token selected Mapbox. That conflated two different
things: having a token is a capability, wanting Mapbox is a decision, and only
the decision belongs in this function. It now reads explicit || 'maplibre'.

The token is still honoured for what it is — with provider:'mapbox' it
authenticates the map, and the token argument stays in the signature because
callers pass one they hold outside the config. It simply no longer votes.

The migration surface is exactly one shape: a host that pasted a real token into
a published embed snippet and set no provider. All 36 shipped snippets carry a
tk placeholder and no provider key, so any host who filled one in is in it. An
unfilled snippet was already MapLibre, because hasMapToken rejects YOUR_
placeholders, and the DX Life branches pass no token at all. Such a host keeps
Mapbox by adding "provider":"mapbox"; ?provider= and window.MAP_PROVIDER are
unchanged.

The gate's four token-selects-Mapbox assertions were the old specification, so
they are inverted rather than deleted — the diff should show what changed for
whom. Two are added: the opt-in still works with a token in hand, which is the
path a migrating host takes, and a real token is still SEEN, asserted apart from
the engine because otherwise the engine could be right while authentication
broke silently.

check:map-props-unit was not in gates:pre, so it proved nothing on a normal run.
It is now, and the suite reads 32 of 32 with it named.
2026-09-28 17:53:38 +00:00
..
api The people-group list is a universal prop: the same maps can show any project's list 2026-09-26 05:16:02 +00:00
charts The language tree becomes anyone's, and the numbers nobody wrote down get written down 2026-09-28 17:40:34 +00:00
colors The legends mirror now, and their labels never became their values 2026-09-26 22:06:58 +00:00
components Fix two defects in the floating note, one of which I committed broken 2026-09-28 17:53:38 +00:00
composables Auto resolves to MapLibre; a token no longer picks the engine 2026-09-28 17:53:38 +00:00
constants Every runtime CDN script and stylesheet is an exact version with an integrity hash 2026-09-26 05:50:24 +00:00
data Country names in the reader's language, for all 242 2026-09-27 04:14:31 +00:00
elements Five plugins were silently monolingual, because the bootstrap was copied sixteen times 2026-09-28 17:40:34 +00:00
i18n zh reads in Simplified throughout: 27 strings that were in Traditional 2026-09-28 17:40:35 +00:00
layouts Wire the back-to-top on both surfaces, from the side that owns the scroller 2026-09-28 17:40:35 +00:00
lists List names speak the reader's language: listLabel and listDefinition 2026-09-26 08:39:52 +00:00
maps The poster sliced its rows in degrees, and Mercator charges more for a degree up north 2026-09-28 17:53:38 +00:00
packet Name the rings on the packet's centered set 2026-09-28 17:53:37 +00:00
packets Number({value:"1"}) is NaN, so the whole reachedness sentence vanished 2026-09-28 15:52:47 +00:00
scripts Hold the packet's ring names to the screen's, and adopt its exact words 2026-09-28 17:53:37 +00:00
stores Make the map's clustering picker real: four options, four different maps 2026-09-25 16:16:46 +00:00
styles Fiord: the MapLibre dark that actually looks like the map it replaces 2026-09-24 02:26:14 +00:00
utils Shipped comments describe the behaviour instead of quoting a person 2026-09-28 17:40:35 +00:00
vendor/cldr Country names in the reader's language, for all 242 2026-09-27 04:14:31 +00:00
index.js Move internal files out of the repo; fix five dead links; a fuller delegation diagram 2026-09-25 05:14:10 +00:00
ProfileLoader.vue ?lang= on the page turns every embedded map's direction and data language, not only its text 2026-09-27 06:42:54 +00:00
README.md Complete app-profiles->plugin-designs sweep across comments/docs; build green; layouts kept at root (load-bearing) 2026-09-17 18:18:19 +00:00

library/ (@map) — the shared map template

The other half of the architecture (see ../plugin-designs/README.md): every map in plugin-designs/<your-map>/ composes the reusable, parameterized pieces that live here. Fix something here and every map benefits on the next build; break something here and every map breaks — read components/WARNING.md before touching shared pieces.

Folder What lives there
ProfileLoader.vue The root of every bundle: parses profile-config, loads the profile, provides the stores + config
components/ Shared UI — map, legends, controls, popup (PeopleGroupDetail), tables, charts, hints (README)
composables/ Shared logic — map engine (useMapInstance), provider switch, shadow-DOM styles, theming
stores/ Per-instance Pinia stores (ui / map / data) — provided by ProfileLoader, injected by children
api/ Data-source registry (sources.json) + fetch layer — the JAMstack runtime wiring
colors/ Color sets maps opt into via profile-config.colorSet
i18n/ The shared string catalogs (all maps speak the same languages)
data/ Small shared datasets baked at build time (big served data lives in ../data/)
constants/ Shared constants
scripts/ Maintainer pipelines (posters, research) — not part of any bundle

The rule of thumb (same as WARNING.md): custom code in your app-profile, reusable code here — and things only move from the first to the second once they've earned it.