The cap-5 shell's "Simple Research" tab rendered an error panel instead of the map, in both trees: Could not load <doxa-research-map> from ../../doxa-research-map/ doxa-research-map.js StackLayout already anchored sibling-bundle srcs to the tree root, but it anchored on the /doxa-maps/ segment of window.location.pathname. The studio mounts at the SERVER ROOT (/index.html), which has no such segment, so the lookup missed and the literal '../../' was returned untouched. The browser resolved it against '/', where '../' cannot climb, and requested /doxa-research-map/doxa-research-map.js — 404, both children, empty stack. That is why it survived: every gate and every screenshot used a LEAF url, and the studio is the one host that is not one. The same composite at its own leaf renders perfectly. resolveBundleSrc now falls back to bundleTreeRoot() — the bundle's OWN script URL, which rollup rewrites to document.currentScript.src in the IIFE build. That is a fact about where the code came from, not a guess about where the page is, which is the lesson stack-demo.vue wrote down when this defect appeared for the third time. It returns null in dev ESM and for any non-<name>/<name>.js layout, so it never guesses. The pathname rule stays FIRST and the untouched-string fallback stays LAST, so every path that worked before is byte-identical: this can still only fix a path, never break one. research-map-plus-grid also adopts stack-demo's bundleSrc() dev/prod helper. In dev, vite serves entries at /plugin-designs/<bundle>/index.js and there is no <bundle>/<bundle>.js to reach, so the dev surface 404'd too. import.meta.env.DEV is statically replaced, so the built output is byte-identical to the literal it replaces. Verified in a browser against the built tree, reading the screenshots: studio root -> Simple Research paints the world map with its prayer legend, on the dev server too. Negative-tested: disabling the new fallback and rebuilding restores the exact 404 and the empty canvas. No regression across every StackLayout consumer — rmpg shallow leaf, rmpg deep default/ leaf (the case the pathname rule was written for), spa -> Simple Research, dashboard-plus-grid, stack-demo — and all seven studio dashboards. 7/7 pre, 22/22 bundles, 18/18 post. |
||
|---|---|---|
| .. | ||
| app-wrapper-material | ||
| pane-wrapper | ||
| README.md | ||
| StackLayout.vue | ||
| VerticalTabsLayout.vue | ||
layouts/ — app wrappers
Each folder here is an app wrapper: a host shell that composes doxa-maps plugin-designs (the independently-built custom elements) into one application.
layouts/<wrapper>/ ← the HOST page (not a bundle)
┌──────────┬──────────────────────────────┐
│ sidebar │ mounts an app-profile here │
│ (nav.js) │ ┌──────────────┐ │
│ ├ item │ │ <doxa-map> │ ← a │
│ ├ section│ │ (a bundle) │ micro- │
│ └ folder │ └──────────────┘ frontend │
└──────────┴──────────────────────────────┘
- app-profile = a self-contained custom element (the micro-frontend). app wrapper = the host that mounts them and provides nav/chrome. A wrapper is a host page, not a bundle-in-a-bundle.
- Wrappers today:
app-wrapper-material/,pane-wrapper/. - Icons are inline SVG only (no CDN) — an F-Droid/offline hard requirement.
Sidebar contract, target filtering, sidebar modes, staging: ../documentation/architecture/app-wrappers.md.