diff --git a/docs/README.md b/docs/README.md index e57791cb4..b03aa89bc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,6 +13,7 @@ - **[reference.md](./reference.md)** — config fields, build scripts, the `profile-config` contract. - **[explanation.md](./explanation.md)** — the model in 15 lines. - **[architecture/](./architecture/)** — the deep end: full contracts, the per-file catalog. +- **[README-embed-example.md](./README-embed-example.md)** — the drop-in README used when this bundler is embedded inside a host repo. Nothing on the simple path is longer than a few minutes; everything complex lives in `architecture/`, linked from where you'd need it. diff --git a/docs/how-to.md b/docs/how-to.md index a6d8815c4..1f63d57b2 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -9,10 +9,10 @@ The three zones govern everything: **reuse `library/` (`@map`), build in **Pick your task:** [embed on a site](#embed-a-map-on-a-partner-site) · [link/iframe directly](#link-or-iframe-a-map-directly-zero-effort-embed) · -[add a map](#add-a-new-map-profile) · [imitate a profile](#imitate-an-existing-profile-dont-re-derive-it) · +[add a map](#add-a-new-map-profile) · [preset variants](#ship-n-preset-variants-of-one-screen-instances) · [imitate a profile](#imitate-an-existing-profile-dont-re-derive-it) · [change colors](#change-colors) · [choose a CDN](#where-do-the-maps-get-served-from) · [build a SPA](#compose-maps-into-a-spa-the-app-shell) · [mobile app](#build-the-android--ios-app-optional) · -[API + token](#set-the-api--mapbox-token) · [agent guardrail](#give-your-agent-the-guardrail) · +[swap engine](#swap-the-map-engine-mapbox--maplibre) · [API + token](#set-the-api--mapbox-token) · [agent guardrail](#give-your-agent-the-guardrail) · [troubleshooting](#troubleshooting) --- @@ -109,6 +109,30 @@ with `_` or `.` — those are skipped by the build. --- +## Ship N preset variants of one screen (instances) + +One parameterized profile can emit **many standalone embed pages** — no extra `.vue`. Drop a +`.instances.json` next to the profile: + +```jsonc +{ + "profile": "doxa-simple-map", + "apiBaseUrl": "https://…", // optional + "instances": [ + { "id": "prayer", "title": "Prayer Map", + "props": { "instanceId": "embed-prayer", "dataSource": "pray-tools", + "tabs": [{ "id": "prayer", "colorStrategy": "prayer" }] } } + ] +} +``` + +`bun run build` then emits a page **per instance** at `doxa-maps///index.html` — +each directly linkable/iframe-able with its preset props baked into the page (the base profile +still accepts live props). Instances *split* one profile into many render targets; `tabs` +*nest* many views into one element — different tools. + +--- + ## Imitate an existing profile (don't re-derive it) You have a map that works and want a second one that behaves almost the same. **Copy the @@ -252,6 +276,29 @@ open `capacitor/ios` in Xcode. Same `webDir: public`. --- +## Swap the map engine (Mapbox ↔ MapLibre) + +The engine is a **runtime parameter** — same bundle, no rebuild. Resolution order +(first defined wins): `profile-config.provider` → `?provider=` in the page URL → +`window.MAP_PROVIDER` → default `mapbox`. + +```html + + + + +https:///doxa-maps///index.html?provider=maplibre +``` + +`maplibre` runs token-free on the OpenFreeMap style (the right GL script/CSS is injected +automatically); the geocoder search bar keeps working in both engines. `mapbox` (the default) +behaves exactly as before — existing embeds never change. + +> Status: shipping on the `feat/map-provider-swap` branch; MapLibre rendering of some pin +> layers is still being verified — treat `maplibre` as preview until merged. + +--- + ## Set the API + Mapbox token Both the data backend and the Mapbox token are **runtime inputs**, never baked into a bundle. diff --git a/docs/reference.md b/docs/reference.md index 392d48cdd..d12b19f41 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -81,6 +81,8 @@ built bundle re-points to different data/colors/language with **no rebuild**. "dataSource": "pray-tools", // or { "type":"rest-api","endpoint":"https://…" } "colorSet": "default", "locale": "en", + "provider": "mapbox", // map engine: "mapbox" (default) | "maplibre" (preview); + // also flippable per page via ?provider= or window.MAP_PROVIDER "tabs": [ /* parameterized screens read this */ ] }'> ``` @@ -133,6 +135,11 @@ each profile/instance page is a standalone, directly linkable/iframe-able map `public/doxa-maps/manifest.json` with ready-made `embed.iframe`/`embed.script` snippets for every profile. Full design: [architecture/embeddability.md](./architecture/embeddability.md). +**Preset instances.** A `.instances.json` beside a parameterized profile +(`{ profile, apiBaseUrl?, instances: [{ id, title?, props }] }`) makes the build emit one +standalone page per instance at `//index.html`. Recipe: +[how-to.md](./how-to.md#ship-n-preset-variants-of-one-screen-instances). + **Bun is required.** `bun.lock` is the committed lockfile; `bun x vite` runs project-local Vite. `npm run …` resolves the same scripts but Bun must be on PATH.