## 3. CLI commands + required installs (per deployment method) Everything runs through `bun` and the scripts in `package.json`. The build loop iterates every folder under **`plugin-designs/`** (each folder = one bundle), so once a map exists there, `bun run build` picks it up automatically — no per-map wiring. > **Install once (all methods):** [Bun](https://bun.sh) (`curl -fsSL https://bun.sh/install | bash`) — Node ≥ 18 also works (`npm run ``` **The hash changes on every build**, so always copy it from the current `manifest.json`. The element takes props and emits events, so it can wire into the surrounding page. **On a partner's site, a JS embed needs two values an iframe does not.** An iframe carries its own document base; a script runs in the host's document, so relative asset and API paths would resolve against the host and 404. The snippet already ships both: | | iframe | JavaScript embed | |---|---|---| | `assetsBase` | not needed | **required**, in `profile-config` (`YOUR_TREE_URL/assets` until you set `assetsBaseUrl`) | | API base | not needed | **required**, `window.MAP_APP_API_URL` (a host global) | | Mapbox token | inherited by the leaf page | replace `YOUR_MAPBOX_TOKEN` | ### 4. WordPress / Disciple Tools — proof of concept **No plugin needed for the simple path:** build, then paste the iframe or script snippet into a WordPress **Custom HTML** block. **The plugin path:** `deployment/wordpress/doxa-maps-embed/` adds a `[doxa_map]` shortcode and a Gutenberg block, registering the bundle through WordPress's own dependency graph so the SRI hash and `crossorigin` survive and the script loads once per page. ```bash bun run check:wp-embed # renders the REAL shortcode with no WordPress installed ``` **What is proven, and what is not.** The check renders the shortcode against the real `manifest.json` and asserts the element tag, valid `profile-config` JSON, the script `src`, the injected SRI hash and `crossorigin` — and rejects a malformed hash. It does not prove that WordPress renders the page or a browser runs it; that needs a live install (`wp-env start`, see `deployment/wordpress/doxa-maps-embed/HOW-TO-TEST.md`). ### 5. Desktop — Tauri — proof of concept **Install:** Bun for the check. For the binary: Rust (`rustup`), the Tauri CLI (`cargo install tauri-cli`) and the platform's webview libraries. ```bash bun run check:tauri # contract check — needs NO Rust, NO Tauri CLI bun run tauri:build # the binary and a .deb — needs the toolchain above ``` **The desktop app wraps the same tree.** `deployment/src-tauri/tauri.conf.json` points `build.frontendDist` at `../public`, the desktop twin of Capacitor's `webDir`; the Rust crate carries no application logic. `check:tauri` asserts that path resolves, every window `url` exists in the built tree, the identifier matches Capacitor's `appId`, and the crate files are present. **Token caveat:** a Tauri webview serves from `tauri://localhost` (or `http://tauri.localhost` on Windows), so a `tokenUrl` endpoint must send CORS headers for that origin. The fix is a response header on the token host, not a change in `tauri.conf.json`. Details: [`deployment/src-tauri/README.md`](../deployment/src-tauri/README.md). --- ## Notes and history The measurements behind the sections above. - **Mobile — `check:mobile` needs no toolchain (verified 2026-09-20).** With `java`, `gradle`, `adb` and `sdkmanager` all absent, sync exited 0, the whole `public/` tree was staged into the native assets and `cap:verify` passed; removing `index.html` made it exit 1. The doc once said "21 bundles staged"; that count named the wrong unit (`cap sync` copies `webDir` wholesale) and went stale, so it says "the whole tree" now. - **JavaScript embed — foreign-host run (2026-09-20).** Both embed methods were run on a foreign host page until they failed: the iframe needed nothing; the script embed needed `assetsBase` and the API base, which the snippet now emits. Same-root and foreign-host both then passed (map painted, attribution shown, 0 errors, 0 404s). - **WordPress — corrected 2026-09-20.** This section once said no WordPress build step existed; the shortcode + block plugin and its contract check were added after. The check stubs the ~20 WordPress functions the plugin calls (`deployment/wordpress/tests/`). - **Tauri — the build ran (2026-09-21).** With the real toolchain (`tauri info` all ✔: webkit2gtk 2.50.6, rustc/cargo 1.96.1) `bun run tauri:build` produced a 65 MB ELF executable and a 58 MB `.deb` (`Depends: libwebkit2gtk-4.1-0, libgtk-3-0`); a later run measured 67 MB and 60 MB. The web tree is compiled into the binary, which is why the `.deb` holds only 6 entries. `bundle.targets` is `["deb"]` because `rpmbuild` and `linuxdeploy` were absent, so `"all"` would fail two formats at the end of a ~6-minute build. The window has not been opened: the build box is headless, and the binary stops with "Failed to initialize GTK" (no display, not a defect). `check:tauri` is negative-tested five ways (wrong `frontendDist`, missing window url, identifier drift, empty windows array, missing crate file).