JAMstack bundler for embeddable map applications
Find a file
doxa-maps-88655c70 a7f57c117d
Some checks are pending
build-gate / build (push) Waiting to run
poster cards: a blue outline on hover, and a gate that can see it
The card asks for the Pinterest/Instagram behaviour: hovering a poster outlines
it in blue so a reader knows which one their click is about to act on.

★ THIS IS NOT A RESTORED BORDER. Several reports asked to bring back "the blue
outline around the poster", and MEASURED 2026-09-24 there has never been one:
all 136 elements painting a frame on this wall compute outline:none, and every
border is grey (.card #e3e6ea, .main #dfe3e7). Nothing regressed -- the
affordance was never built. The reports kept recurring because a hover state is
invisible to a screenshot, so each check confirmed "no outline" and concluded
the sighting was mistaken.

outline, NOT border, and that is load-bearing. An outline paints OUTSIDE the
box and takes no space, so it cannot move anything. The rest of this wall's gate
asserts where the print row sits at five widths; a hover that grew a border
would re-lay-out the card and push that row, so a cosmetic state could break a
gate about print controls.

:focus-within carries it to the keyboard, and @media (hover:none) drops the
whole state on touch -- with no pointer it would either never appear or stick
after a tap, leaving a card looking permanently selected.

THE GATE NOW MOVES THE POINTER. Everything it measured before was of a loaded,
untouched page, which is precisely why this affordance could go unbuilt while
being repeatedly requested.

⚠ AND ONE OF MY OWN ASSERTIONS WAS DECORATION UNTIL I MUTATION-TESTED IT. I
first asserted the card's OUTER width is unchanged by hover. It can't change:
the card is a grid item, so the track fixes its width and a border grown on
hover eats inward. MEASURED with border-width:4px on hover -- outer 224->224px,
unfalsifiable, while the CONTENT box went 222->216px. It now asserts clientWidth,
which is what actually repositions the print row.

MUTATION-TESTED: remove the outline -> FAIL at all four pointer widths (exit 1);
grow a border alongside it -> FAIL naming the content-box shift (exit 1);
restore -> PASS (exit 0), reporting "hover 2px rgb(47, 111, 219)" at 768-1920
and "no outline (touch, correct)" at 390.

The print/open controls the card also asks for are already there and were
verified clickable in the same pass: Prayer List, Card Deck, the stock select
and Poster Map, all four with full labels and real handlers, 0 clipped.
2026-09-24 23:17:42 +00:00
.claude Status line: which plugin this session is working on 2026-09-24 00:26:24 +00:00
.forgejo/workflows build gate: "not measurable" was wrong, and it is why this sat unmoved 2026-09-24 15:19:56 +00:00
.github/workflows doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
_archive/staging-surface-2026-09-22 Archive the repo-root staging page; the studio is the only entry now 2026-09-22 14:34:58 +00:00
data Stop the tables saying GRN is missing and miscounting their own rows 2026-09-24 22:46:16 +00:00
deployment Commit Cargo.lock: it was ignored by association with real build output 2026-09-22 06:53:27 +00:00
documentation README: UPG-100 is the mobile app, shot at its owner's "ready at 88a566f" 2026-09-24 22:03:50 +00:00
internal poster cards: a blue outline on hover, and a gate that can see it 2026-09-24 23:17:42 +00:00
library poster cards: a blue outline on hover, and a gate that can see it 2026-09-24 23:17:42 +00:00
plugin-designs Merge branch 'main' of https://git.nuxtbase.app/doxa-life/doxa-maps into bundler-3/work 2026-09-24 23:01:56 +00:00
public poster cards: a blue outline on hover, and a gate that can see it 2026-09-24 23:17:42 +00:00
serving Research Gallery: embed on someone else's page, in both modes 2026-09-24 19:03:37 +00:00
skills/make-a-doxa-map consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
.env.example doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
.gitattributes Rename app-profiles -> plugin-designs; build green under new naming (load-bearing paths updated, guards pass) 2026-09-17 18:18:18 +00:00
.gitignore Move the private field-access dataset out of the repo 2026-09-24 18:34:01 +00:00
AGENT-BRIEF.md Unescape the pipe in the prose line 2026-09-24 21:51:11 +00:00
bun.lock emit a real desktop binary and .deb for deploy method 5 2026-09-21 21:36:18 +00:00
capacitor.config.json consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
LICENSE doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
package.json gate: what readers are SERVED must be what we BUILT 2026-09-24 22:56:56 +00:00
README.md README: UPG-100 is the mobile app, shot at its owner's "ready at 88a566f" 2026-09-24 22:03:50 +00:00
vite.config.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
vite.doxa-maps-build-config.json Land the swarm's work: no iframes anywhere, a tree that keeps its shape, deeper facets 2026-09-22 14:51:52 +00:00

dx-maps — one build, maps that embed everywhere

Write a map once in plugin-designs/<your-map>/, run one build, and drop it on any site — iframe, script embed, mobile app — or open every map at once as one app. Five plugin capabilities, five deployment methods, one shared library, one build.

What dx-maps set out to do Proof
One build → one folder you can drop on any host bun run check:drop
Every map embeddable from a copy-paste snippet deployment methods · bun run check:embed-targets
Every map interoperable through props and events bun run verify:interop
One app nests every map — and each stays embeddable on its own capability 5 · bun run check:composite-reg
5 capabilities × 5 deployment methods bun run verify:5-caps
Shared library, private plugins — reuse without breaking each other bun run check:library-index
One agent per plugin, one shepherd, one green main agent swarm

The 5 plugin capabilities

A capability is how much a plugin nests, from one element (1) to an app of apps (5). Every screenshot is a real bundle from this repo's build.

One plugin, one element (<doxa-maps-spa>), and every tab inside it is a real plugin from a lower tier that you can still embed on its own. plugin-designs/doxa-maps-spa/

Capability 5 — the Research Gallery app shell (doxa-maps-spa)

What the Research Gallery is made of — all five capabilities in one plugin
Research Gallery                          <doxa-maps-spa>          capability 5
├─ Dashboards
│  ├─ Big Picture                         dashboard-plus-grid      capability 4
│  │   ├─ research dashboard              research-dashboard       capability 3
│  │   └─ people-groups grid              people-groups-grid       capability 2
│  ├─ Simple Research                     research-map-plus-grid   capability 4
│  │   ├─ research map                    doxa-research-map        capability 3
│  │   └─ people-groups grid              people-groups-grid       capability 2
│  └─ Regions                             regions-mfe              capability 4
│      ├─ regions list                    regions-list             capability 1
│      └─ region dashboards               region-dashboards        capability 1
├─ Prayer Mobilization
│  ├─ UPG-100 List                        upg-100-mfe              capability 4
│  │   ├─ list                            upg-100-list             capability 1
│  │   └─ poster wall                     poster-wall              capability 1
│  └─ Prayer Progress                     doxa-simple-map          capability 2
├─ Gospel Research
│  ├─ Cities with Internet                connectivity-map         capability 1
│  └─ Gospel Resources                    resources-map            capability 1
└─ Experimental                           every other bundle, discovered automatically

Capability 4 — composite: plugins wired together

Nests lower-tier plugins and wires them with props and events. plugin-designs/my-upg-100-list/

Capability 4 — the UPG-100 composite (my-upg-100-list)

List (cap 1, embeddable alone) Poster wall (cap 1, embeddable alone)
UPG-100 list leaf UPG-100 poster-wall leaf

Capability 3 — multi-view: many views, one element

plugin-designs/doxa-research-map/

Capability 3 — the monolithic research map (doxa-research-map)

Capability 2 — presets: one plugin, many maps

One root.vue plus a preset table. plugin-designs/doxa-simple-map/

Prayer Engagement Adoption
Capability 2 — prayer preset (doxa-simple-map) Capability 2 — engagement preset (doxa-simple-map) Capability 2 — adoption preset (doxa-simple-map)

Capability 1 — single element

One folder, one .vue, one element. plugin-designs/all-people-groups/

Capability 1 — a single-element plugin (all-people-groups)

Which bundle sits at which tier is generated, not remembered: documentation/reference-capability-exemplars.md.


The 5 deployment methods

1. iframe — the prayer map on any site ✅ production

One <iframe> tag, no build step. Copy the embed.iframe snippet from manifest.json.

Method 1 — the prayer map embedded in a host page's iframe

2. Mobile app — UPG-100 on a phone ✅ built

The UPG-100 prayer lists and posters, shipped on their own as a Capacitor app: one poster per row, print options that wrap to fit. bun run check:mobile · bun run phone (needs Android SDK + JDK 17)

Method 2 — the UPG-100 list at phone size

The whole capability-5 app on the dx-life research page, from one <script src> and one element — replacing the separate research map, list and regions dashboards the page used to carry. Copy the embed.script snippet (SRI-pinned) from manifest.json.

Method 3 — the Research Gallery JS-embedded on the dx-life research page

4. WordPress / Disciple Tools plugin — 🧪 proof of concept

A shortcode + block plugin in deployment/wordpress/; its contract test passes (bun run check:wp-embed). Proven, not production-ready.

5. Desktop app (Tauri) — 🧪 proof of concept

A desktop binary and .deb build from deployment/src-tauri/ (bun run check:tauri). Proven, not production-ready.

Mapbox token: the dev server bakes one in; built pages take ?tk=pk.…, a pasted token, or a token endpoint. Or skip Mapbox entirely: provider: "maplibre" on any instance renders on MapLibre with no key. Every command and prerequisite: documentation/README-SECTION-3-cli-commands.md.


Build it with an agent swarm

Every plugin has one agent responsible for building it, working in its own git worktree. The plugins live together in the Plugin Studio — one repo, one shared library — and one shepherd makes sure every agent is doing its job well. Changes land on main through a merge queue (the model behind GitHub's merge queue and GitLab's merge trains): one at a time, rebased and gated.

The delegation model: the Plugin Studio at the centre, a ring of plugins around it, one agent per plugin outside that, and one shepherd over all the agents

# one worktree + one agent per plugin
git worktree add -b regions/work ../dx-maps-regions main
git worktree add -b upg100/work  ../dx-maps-upg100  main

# one dev server per agent, each on its own port
bun x vite --port 5301 --strictPort

# land through the queue: one at a time, rebased, gated
flock /tmp/dx-maps-main.lock sh -c '
  git fetch origin && git rebase origin/main &&
  bun run gates:pre && git push origin HEAD:main'

One agent owns the full build (it wipes the shared output first); everyone else checks their own bundle with BUNDLE=<name> bun x vite build. Agents joining this repo: read AGENT-BRIEF.md. Diagram source: delegation-model.svg.


The Plugin Studio — ★ where you work

Every plugin in one place, sorted by capability. Pick any plugin to run it live, see what it is composed of, and copy its embed code. Tell your agent which plugins to group, and it composes them into a higher-capability plugin with props, events and a layout — that is how the Research Gallery was built. (The studio is being redesigned; this screenshot tracks it.)

Capability 5 — the developer studio (plugin-studio)

Get it running

You need git, Bun and Node ≥ 18.

git clone https://git.nuxtbase.app/doxa-life/doxa-maps.git
cd doxa-maps
bun install --frozen-lockfile
bun run dev                     # → http://localhost:5173/  is the Plugin Studio

No build needed first — the built tree is committed. To start a plugin, copy plugin-designs/template-bundle/ to plugin-designs/<your-map>/; the studio finds it automatically.

Command What it does
bun run dev The Plugin Studio, hot-reloading, at http://localhost:5173
BUNDLE=<name> bun x vite build Build one bundle only
BUILD_ALLOW=1 bun run build The full deployable tree in public/doxa-maps/ (~4 min; refuses without the flag, to protect a shared tree)
bun run serve Serve the built tree at http://localhost:4173
bun run check:settled Exit 0 = the built tree is safe to measure right now
bun run gates:pre · bun run gates:post The verification gates
bun run shots Regenerate these screenshots (ONLY=<name> for one)

Repository layout

plugin-designs/   YOUR maps — one folder per plugin, a free zone
library/          the SHARED toolkit (layouts, components, composables) — a high bar
public/doxa-maps/ the build output: the drop-anywhere tree + manifest.json
deployment/       Capacitor · WordPress · Tauri
internal/         the build generator and the gates
documentation/    tutorial · how-to · reference · architecture — start at documentation/README.md

Maps should be open source, run everywhere, and multiply. One build makes each map a self-contained file for your site, your partners' sites and a phone. The Plugin Studio is where you compose them into something bigger.