verify:full runs two browser guards that `bun run verify` skips, and both were failing. Neither was a product defect; both had rotted unnoticed precisely because verify-all.mjs marks them `browser: true` and skips them unless --full is passed, so the build chain has never run them. verify-app-tables was broken four ways, each of which alone made it useless: Its default port was 8917, which nothing in this repo has ever bound. Now 4173, the port `bun run serve` binds, so it runs with the same server as every other browser gate. APP_BASE still overrides. It navigated to `index.html#key-city-posters` and two sibling fragments, resolved against the PROFILES object in layouts/app-wrapper-material. That shell is not what `/` serves — as of 2026-09-22 the root page mounts <plugin-studio>, and the built root contains ZERO of those three keys. The list is now three real profile paths taken from manifest.json. key-city-posters is dropped rather than renamed to something that merely looks similar: no such profile ships. Its "are we on our page" check matched the shell title "Doxa Maps". A leaf titles itself "<profile> · <bundle>". My first replacement matched an absolute script path and was equally wrong, because a leaf references its bundle relatively (src="../gospel-resources.js") — measured, on a page that was fine. It now matches the SRI integrity attribute, which this build guarantees by construction and no other server emits. Its row counter only counted rows ONE level inside a shadow host, with no seen set. A row in the light DOM, or one shadow level deeper, counted zero. Now walks every depth. The last defect is the one worth reading twice. The app header printed near the END of the loop body, after the row check, so every verdict appeared ABOVE the app it described and the whole report was offset by one. That made a PASSING app (gospel-resources/data-tables, 40 rows) look like the failure and the real failure look like it had rendered rows. I chased the wrong app through three rounds of instrumentation before reading the output in order. A report that is correct but misordered costs a wrong diagnosis, not just time. Read correctly, the guard now says: cities-internet/data-tables 40 rows and 1 table fetched; gospel-resources/data-tables 40 rows and 1 table fetched; and gospel-resources/resources-list fetches NOTHING and renders nothing. That last one is the already-carded gospel-resources data gap, waiting on the three Driver decisions — the component is built and correctly showing an empty result for data it was never given. So the guard is reporting one real, known, Driver-gated absence, which is what it is for. Everything else in it was already sound and is untouched: the recursive shadow-root walk for row counting, fail-closed on zero fetches, and third-party request detection, which the file rightly calls a persecution risk rather than a performance note. |
||
|---|---|---|
| .. | ||
| api | ||
| colors | ||
| components | ||
| composables | ||
| constants | ||
| data | ||
| i18n | ||
| layouts | ||
| maps | ||
| scripts | ||
| stores | ||
| styles | ||
| utils | ||
| index.js | ||
| ProfileLoader.vue | ||
| README.md | ||
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.