doxa-maps/library
doxa-maps-88655c70 301cc38fba
Some checks are pending
build-gate / build (push) Waiting to run
feat(upg-100): print a prayer packet from the map legend
Driver, as a first-time user: "I select one and it gives me print options at
the top right of the legend... that's the only way that map would be usable."

The affordance was already built and switched OFF. The shared legend emits
'export' with 'poster' | 'packet' for the selected node, the profile wired
@export, and SHOW_EXPORT_BUTTON was held false with the note "until the export
packet is finished: the button currently produces a broken packet". That
precondition is now met, so the switch is on.

ONE RENDERER, TWO CALLERS. The pages move to library/packet/packet-render.js,
imported by BOTH the build-time generator and the browser export, so the printed
packet and the generated one cannot drift. The card asked for exactly this:
"reuse the existing print actions rather than growing a fourth implementation."
The extraction is behaviour-preserving — the generated packet is byte-identical
to before apart from leading whitespace (the code is now inside a factory), and
check:packet-render still passes 8/8.

★ THE PACKET IS GENERATED ON CLICK, NEVER SHIPPED. One packet is ~3.5 MB (photos
dominate) and 28 zones would add ~100 MB to a repo that ALREADY had a publish
blocked at a 74 MB asset tree. Generating client-side costs zero repository
bytes; the photos come from URLs the records already carry. This is the Driver's
instruction: "instead of fetching the poster from the public folder I want the
client side code to generate the poster real time when you click on the button
so it does not take a lot of mb storage." Bundle cost: +21 KB (494 -> 516 KB),
which includes all 12 prayer points and Mark 5:1-20 in full.

Printing goes through the SHARED openPrintFrame — a hidden same-page iframe, not
window.open(). A popup is blockable and drops the reader out of the map.

Two traps the browser path had to handle, both already known to this codebase:
  - pg_slugs BYPASSES the shared selector evaluator (it intentionally throws on
    that type, and 12 of the 27 lists use it). Same special-case the map and the
    poster wall apply, so all three agree about who is in a list.
  - evaluate() returns a Set, not an array.

VERIFIED IN A BROWSER, not by reading source (new gate check:packet-browser):
live records -> shared renderer -> page.pdf(), giving 8 sheets -> 8 pages at
612x792pt, 95 people cards, 12 wheel segments, Mark 5 in full, 2 metacamp.org
attributions, 0 page errors. I18n verified with a partial Spanish block: the
translated headings rendered in Spanish while Mark 5 and the attributions fell
back to English, per key, never blank.

Card BUILD-UPG100-MAP-LEGEND-LEADS-WITH-THE-UPG-100-LIST part (d). Parts (a) and
(b) shipped earlier. Part (c) — removing the People Group tab and retabbing the
legend — stays OPEN: that card is explicitly driver_gated on "what is the
legend's tree once Region/Zone/People Group are removed", and the current tabs
are wired to real hierarchy data.
2026-09-24 02:43:49 +00:00
..
api Add the Gospel Access filter, the ladder the binary flag was flattening 2026-09-23 13:19:22 +00:00
colors A validated WAGF region palette, where the one-palette gate requires it 2026-09-24 02:24:08 +00:00
components feat(upg-100): print a prayer packet from the map legend 2026-09-24 02:43:49 +00:00
composables Vendor Poppins: the body face every line of text on these pages uses 2026-09-24 02:05:56 +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 Merge main into bundler-2/work 2026-09-23 23:48:10 +00:00
maps Load the RTL text plugin from one place, and in the composite too 2026-09-22 19:55:58 +00:00
packet feat(upg-100): print a prayer packet from the map legend 2026-09-24 02:43:49 +00:00
scripts feat(upg-100): print a prayer packet from the map legend 2026-09-24 02:43:49 +00:00
stores fix(spa): make embedded maps survive the sandboxed plugin iframe 2026-09-12 21:07:26 +00:00
styles Galaxy basemap: swap to VersaTiles Colorful, a found production style 2026-09-23 20:50:31 +00:00
utils Resolve the shared asset base per bundle, so nested tabs stop 404ing 2026-09-23 12:14:52 +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 One page, one map token — and the nested search bar comes back 2026-09-24 01:14:37 +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.