doxa-maps/library
doxa-maps-88655c70 3a7913df64 Record why the table generator keys by ISO code and never by name
Extending last tick's external-source check from legends to the baked tables
turned up a real discrepancy: gaps-and-opportunities.json has 2,106 rows against
a 2,107-row corpus, with five name mismatches. The table says "Jerba" and
"Tmagourt" where the live API now says "Amazigh of Djerba" and "Amazigh,
Matmata" — the same Tunisian peoples, relabelled upstream since the snapshot.

It is harmless, and the reason is the point. Nothing joins on the name: the
generator keys everything by iso639_3, and the consumer does the same at
resources-map.vue:194, whose comment already states the rule and its stake —
"Never a name match: language names collide and drift ... a fuzzy hit here would
put the wrong scripture in someone's hands."

The generator followed that rule in four places and never said why. So the
decision lived only in the consumer and in my head, and a future author tidying
this file toward a name join would find nothing to stop them. They would
silently drop three groups and orphan two rows: no error, no empty state, just
fewer people on a map about people nobody has reached. That is precisely what
check-label-joins.mjs was written to prevent.

Verified rather than asserted before writing it down: the join key is clean on
every row — heart_iso639_3 present and well-formed on all 2,106, zero blank,
zero malformed, 862 distinct codes; bridge_iso639_3 blank on 461, which is
expected because not every group has a bridge language. gospel-resources/
data-tables renders 50 rows by 21 cells with zero console errors and zero
responses >= 400. Both citations in the new comment were checked against the
files they name.

Comment only; no behaviour change. Five gates pass, including check:label-joins
itself and check:legend-source from last tick.
2026-09-23 11:06:11 +00:00
..
api consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
colors Land the swarm's dashboard work: colour, rails, cascade, scroll 2026-09-22 18:57:39 +00:00
components Start the wrapped filter line on the same edge as the one above it 2026-09-23 09:52:58 +00:00
composables Give fitBounds a duration, because FLY_CONFIG alone leaves it instant 2026-09-23 05:01:53 +00:00
constants doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
data docs: simplify all folder READMEs (what's here + graphic + link); migrate complex reference to docs/architecture/{data-sources,i18n,components,app-wrappers,poster-generation}.md 2026-09-11 18:50:31 +00:00
i18n consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
layouts Match the tab radius to the rest of the app, and open on the tab you were last on 2026-09-23 01:03:15 +00:00
maps Load the RTL text plugin from one place, and in the composite too 2026-09-22 19:55:58 +00:00
scripts Record why the table generator keys by ISO code and never by name 2026-09-23 11:06:11 +00:00
stores fix(spa): make embedded maps survive the sandboxed plugin iframe 2026-09-12 21:07:26 +00:00
styles Move the eight CARTO basemap styles to OpenFreeMap 2026-09-22 02:27:48 +00:00
utils Land the prayer facet and the scrim helper 2026-09-22 21:50:32 +00:00
index.js Brand-neutral shared VerticalTabsLayout with lazy nested-element hosting; fix cap-5 prayer tab leaf path; neutralize library identifiers; add Forgejo CI build-gate workflow 2026-09-19 17:24:30 +00:00
ProfileLoader.vue Land the swarm's dashboard work: colour, rails, cascade, scroll 2026-09-22 18:57:39 +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.