README: distinguish the two cap-5 apps (product SPA vs developer studio) and add current capability screenshots

This commit is contained in:
doxa-maps-88655c70 2026-09-20 05:00:01 +00:00
parent 85014aad11
commit e6ac6407c9
8 changed files with 126 additions and 5 deletions

131
README.md
View file

@ -27,8 +27,8 @@ This README is a **show, don't tell** index. Skim the three tables, then jump to
| 1 | **iframe embed** on any site | required | [§2](#deploy-1--iframe-embed) |
| 2 | **Mobile app** (Android / Capacitor) | required | [§2](#deploy-2--mobile-app) |
| 3 | **Direct-JS / research dashboard** (props + events + SRI) | required | [§2](#deploy-3--research-dashboard-direct-js) |
| 4 | **WordPress** (same artifacts, Custom HTML block) | deferred POC | [§3](#3-cli-commands--installs-per-deploy-method) |
| 5 | **Desktop** (Tauri) | deferred POC | [§3](#3-cli-commands--installs-per-deploy-method) |
| 4 | **WordPress** (PHP plugin: shortcode + Gutenberg block) | built, not yet shot | [§3](#3-cli-commands--installs-per-deploy-method) |
| 5 | **Desktop** (Tauri) | aspirational (no code yet) | [§3](#3-cli-commands--installs-per-deploy-method) |
### CLI commands + what to install
@ -96,7 +96,32 @@ the UPG-100 list plugin. The composite (`upg-100-mfe`) plus its list pages:
build. A vertical-tab sidebar groups every plugin by capability (CAP 5 → 1); clicking a row mounts that
plugin. This same SPA is the Capacitor mobile-app entry (see deploy 2).
![Capability 5 — the doxa-maps SPA (all plugins, one app)](docs/readme-images/cap5-doxa-maps-spa.png)
**`plugin-studio` is itself a CAP-5 plugin, AUTO-GENERATED by the Vite build step.** You do not hand-write
it — the build discovers every folder in `plugin-designs/`, bundles each, and generates the studio SPA that
composes them (a `nested-spa-single-spa` / app-shell tier plugin). Add a plugin-design folder, run the
build, and it appears in the studio automatically. (`doxa-maps-spa` is the curated product SPA; `plugin-studio`
is the auto-generated gallery of everything built — same cap-5 tier, both built by `bun run build`.)
**Two shared layouts back the cap-5 tier** (in `library/layouts/`, brand-neutral + reusable by any plugin):
- **`VerticalTabsLayout`** — one element visible at a time (the sidebar-tab shell above). Lazy-mounts each
tab's element on first open.
- **`StackLayout`** — the *opposite*: all elements STACKED top-to-bottom at natural height, so the host page
scrolls through them (the doxa-life / nuxtinator page-flow model). Group two elements and embed the pair.
**The two cap-5 apps, side by side.** They are different products at the same tier and the distinction
matters when you embed one: `doxa-maps-spa` is what an END USER gets, `plugin-studio` is what a DEVELOPER
reviews. (Captioning a studio shot as the product SPA is a documented mistake — see `/plugin-designer`.)
*`doxa-maps-spa` — the curated PRODUCT SPA.* Vertical tabs grouped by audience, not by capability:
Prayer Mobilization (Big Picture · UPG-100 List · Prayer Progress · Gospel Resources) → Research
(Cities & Internet · Research Map) → Experimental. Tab 1 is the cap-4 Big Picture composite.
![Capability 5 — doxa-maps-spa, the curated product SPA](docs/screenshots/cap-5-nested-spa.png)
*`plugin-studio` — the AUTO-GENERATED developer gallery.* The same cap-5 tier, but the sidebar groups every
built plugin by capability (CAP 5 → 1) so an author can review the whole catalogue after a build.
![Capability 5 — plugin-studio, the auto-generated developer gallery](docs/readme-images/cap5-doxa-maps-spa.png)
---
@ -144,18 +169,114 @@ Quick reference:
| 1 | **iframe embed** | Bun | `bun install` → `bun run build` → `bun run serve` (or drop `public/doxa-maps/` on any host) |
| 2 | **Mobile (Android)** | Bun · Android SDK + `adb` · JDK 17 · Capacitor (devDep) | `bun run phone` |
| 3 | **Direct-JS / dashboard** | Bun | `bun run build`, then paste the `<script src> + integrity` snippet from `manifest.json` |
| 4 | **WordPress** | Bun | `bun run build`, then paste the iframe/script snippet into a Custom HTML block *(deferred POC)* |
| 5 | **Desktop (Tauri)** | Rust + Tauri CLI *(not yet scaffolded)* | *deferred POC* |
| 4 | **WordPress** | Bun | `bun run build`, then install the `wordpress/doxa-maps-embed/` PHP plugin (shortcode + Gutenberg block) *(built, not yet shot — plugin written, install never captured live)* |
| 5 | **Desktop (Tauri)** | Rust + Tauri CLI *(not yet scaffolded)* | *aspirational — no Tauri code exists yet* |
Every build writes `public/doxa-maps/manifest.json` — a machine-readable index carrying the ready-to-paste
**iframe** and **`<script src>` + SRI** embed snippet for every map.
---
## 4. Repository layout (hand-off map)
Two directories matter to a plugin author: **`library/`** (the shared, high-bar reusable toolkit) and
**`plugin-designs/`** (your free zone — one folder per plugin). The build reads `plugin-designs/`, pulls
what it needs from `library/`, and emits each plugin to `public/<name>/`.
### `library/` — the shared reusable toolkit
Imported by ANY plugin. High blast radius — see [Library governance](#5-library-governance) before editing.
```
library/
├── index.js ← the library's public surface (what plugins import)
├── ProfileLoader.vue ← the runtime loader that mounts a plugin profile
├── layouts/ ← reusable shell layouts (VerticalTabsLayout, app-wrapper-material, pane-wrapper)
├── components/ ← reusable Vue components (map controls, search, tables, charts, legends, detail panels)
├── composables/ ← reusable logic hooks (useMapData, useMapClustering, useGeocoderSearch, legends/, poster/)
├── colors/ ← brand-neutral color scales + registry (prayer-progress, adoption, engagement, religion, language-family)
├── constants/ ← shared defaults (map defaults, zoom, poster sizes)
├── stores/ ← shared Pinia-style stores (dataStore, mapStore, uiStore)
├── i18n/ ← shared translations (index + locales/)
├── api/ ← data-source layer (DataSourceManager, source registry, sources.json)
├── data/ ← shared static reference data (ISO tables, language-family lookups)
├── utils/ ← shared helpers (clustering, MST/network utils, data-source helpers)
├── styles/ ← shared style registry
└── scripts/ ← shared build/gen scripts (posters, research)
```
### `plugin-designs/` — your free zone (one folder per plugin)
You write your app HERE. Each folder is its own application; on `bun run build` it compiles to
`public/<name>/` and becomes its own deployable custom element (via `defineCustomElement`).
```
plugin-designs/
├── template-bundle/ ← copy this to start a new plugin
├── doxa-vision-card/ ← CAP 1: single element (one .vue + index.js)
│ ├── doxa-vision-card.vue
│ └── index.js
├── doxa-simple-map/ ← CAP 2: preset element (one root.vue + *.instances.json → many maps)
├── doxa-research-map/ ← CAP 3: monolithic multi-view map
├── my-upg-100-list/ ← CAP 4: composite element (nests lower-tier elements)
├── doxa-maps-spa/ ← CAP 5: app-shell (the full doxa-maps app, one deep-linkable SPA)
│ ├── doxa-maps-spa.vue
│ ├── doxa-maps-spa.meta.json
│ ├── doxa-maps-spa.instances.json
│ └── index.js
├── research-dashboard/ ← direct-JS dashboard (props/events/SRI; deploy method 3)
├── big-picture/ country-posters/ key-cities/ cities-internet/ … ← more example plugins
```
**How a plugin-design works:** create a folder in `plugin-designs/<name>/` (copy `template-bundle/`),
write your `.vue` (plus an optional `<name>.meta.json` to declare its type and `<name>.instances.json` for
preset rows), and run `bun run build`. The build auto-detects the folder, compiles it into a self-contained
element at `public/<name>/`, and adds its embed snippets to `public/doxa-maps/manifest.json`. Your plugin
imports shared pieces from `library/` but ships as its own deployable artifact.
### Deploy honesty ledger
This README does not over-claim. Per the verified ledger (2026-09-19):
| Count | State | Methods |
|-------|-------|---------|
| 2 | **proven live** | iframe embed · direct-JS embed |
| 2 | **built, not yet shot** | mobile (Capacitor scaffolded, APK never emitted) · WordPress (`wordpress/doxa-maps-embed/*.php` written, install never captured) |
| 1 | **aspirational** | Tauri desktop (no code exists yet) |
All **5 capabilities** are proven by a built bundle. Only the deploy *methods* carry the two lower states.
---
## 5. Library governance
The two zones above have very different rules. Follow them so one author's change never breaks another's map.
**`plugin-designs/` = free zone.** Agentically engineer your maps here without asking. A plugin operates as
its own application, isolated to its own folder, and builds to its own output — nothing you do here can break
another author's plugin.
**`library/` = HIGH BAR.** It is multi-tenant: reused by many maps and authors. Editing it is a
breaking-change risk to everyone. From the canonical anti-pattern
(`AP-fill-shared-library-with-non-reusable-components`):
> Agentically engineer your maps IN plugin-designs — a plugin operates as its own application that builds to
> the output folder on the build step. Only contribute to the shared library if you're experienced AND the
> component is genuinely reusable + parameterized so OTHER maps (not just yours) can use it. Treat every
> library edit as breaking-change-risk to other tenants — a HIGH BAR. Never widen or casually add.
Why it matters: a non-reusable component in `library/` teaches other agents + future authors that it's OK to
follow the anti-pattern, polluting a high-blast-radius surface over time — and any library edit can make a
breaking change that breaks other tenants' maps. Keep all map-specific, non-parameterized content in your
plugin-design; contribute to `library/` only when it is genuinely reusable and parameterized.
---
## More docs
| Read this | When |
|---|---|
| **[docs/develop-a-plugin-and-see-it-live.md](./docs/develop-a-plugin-and-see-it-live.md)** | ★ START HERE — the golden path, zero → a plugin live, in 6 steps |
| **[docs/README-SECTION-3-cli-commands.md](./docs/README-SECTION-3-cli-commands.md)** | the full per-method CLI + install matrix |
| **[docs/why.md](./docs/why.md)** | 2 min — the problem, the idea, one diagram |
| **[docs/tutorial.md](./docs/tutorial.md)** | build your first map, step by step |

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB