Docs: "reusable by default" in the library guides, and Deep Research by its name
- library/components/WARNING.md, library/dashboards/README.md and documentation/contributing/README.md taught "graduate into the library at the second consumer". They now teach the plugin-designer skill's rule (section 3): a component that could serve more than one map is built once in library/, driven by props, and landed through the build owner; one-off or experimental pieces stay in a map's folder; a new pattern is a pilot, then approved, then rolled out. The contributing guide's "full reasoning" link pointed to an index without it; it now points to the skill. - The app shell doxa-maps-spa is labelled Deep Research. Ten docs still called it the Research Gallery (15 mentions): DEPLOY.md, the desktop how-to, embeddability, develop-a-plugin, reference-universal-props, reference.md, the shell's EMBED.md, and the plugin-designer skill with two of its references. Identifiers (doxa-maps-spa, branch and route names) are unchanged; README.md is not touched.
This commit is contained in:
parent
353bf078c8
commit
70ea389db3
13 changed files with 30 additions and 28 deletions
|
|
@ -106,8 +106,8 @@ Details, per host (Cloudflare Pages, jsDelivr, any web server) and per embed sty
|
||||||
Copy the built `dx-maps/` folder into your site's `public/` (renaming it is fine) and your site becomes
|
Copy the built `dx-maps/` folder into your site's `public/` (renaming it is fine) and your site becomes
|
||||||
the host: no second server and no cross-site setup, because the maps and the page share one origin.
|
the host: no second server and no cross-site setup, because the maps and the page share one origin.
|
||||||
|
|
||||||
**Live example:** DX-life's drop-in branch copies the folder into its `public/` and fills `/research` with the
|
**Live example:** DX-life's drop-in branch copies the folder into its `public/` and fills `/research` with
|
||||||
Research Gallery.
|
Deep Research.
|
||||||
|
|
||||||
**The two routes, on your laptop:** DX-life has one branch per route: `research-gallery-drop-in` (this
|
**The two routes, on your laptop:** DX-life has one branch per route: `research-gallery-drop-in` (this
|
||||||
section, no Docker) and `research-gallery-subdomain` (the dx-maps container on its own address, with
|
section, no Docker) and `research-gallery-subdomain` (the dx-maps container on its own address, with
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ desktop path has never been run by anyone, and the steps say so where that is th
|
||||||
| Piece | State |
|
| Piece | State |
|
||||||
|---|---|
|
|---|---|
|
||||||
| The web tree (`bun run build` → `public/dx-maps/`) | Proven. Every landing builds it. |
|
| The web tree (`bun run build` → `public/dx-maps/`) | Proven. Every landing builds it. |
|
||||||
| The generic Tauri shell (`deployment/src-tauri/`) | Exists. It opens the Research Gallery, builds only a Linux `.deb`, and has never been packaged on macOS or Windows. |
|
| The generic Tauri shell (`deployment/src-tauri/`) | Exists. It opens Deep Research, builds only a Linux `.deb`, and has never been packaged on macOS or Windows. |
|
||||||
| The engine on Linux (`bun run dev`, laptop mic) | Proven. |
|
| The engine on Linux (`bun run dev`, laptop mic) | Proven. |
|
||||||
| The engine taking the **webview's** microphone (`RUDDER_AUDIO=browser`) | Proven on Linux: audio streamed over `/api/rudder/stream` came back as the full test sentence. |
|
| The engine taking the **webview's** microphone (`RUDDER_AUDIO=browser`) | Proven on Linux: audio streamed over `/api/rudder/stream` came back as the full test sentence. |
|
||||||
| The engine **compiling** for macOS (arm64, x86_64) and Windows (x86_64) | Proven by cross-compiling. It has **never been run** on either. |
|
| The engine **compiling** for macOS (arm64, x86_64) and Windows (x86_64) | Proven by cross-compiling. It has **never been run** on either. |
|
||||||
|
|
@ -124,6 +124,6 @@ macOS and Windows the app must do the same on first run:
|
||||||
- `desktop:build` has run on Linux only; the app it produced has not been launched yet. Nothing has run on macOS or Windows.
|
- `desktop:build` has run on Linux only; the app it produced has not been launched yet. Nothing has run on macOS or Windows.
|
||||||
- The macOS/Windows runtime archive layout, and whether the engine's derived path matches it.
|
- The macOS/Windows runtime archive layout, and whether the engine's derived path matches it.
|
||||||
- The first-run download, including resuming an interrupted 742 MB download.
|
- The first-run download, including resuming an interrupted 742 MB download.
|
||||||
- Mapbox basemaps in the Research Gallery need the token host to allow the Tauri origin
|
- Mapbox basemaps in Deep Research need the token host to allow the Tauri origin
|
||||||
(`deployment/src-tauri/README.md`). Rudder itself needs no token.
|
(`deployment/src-tauri/README.md`). Rudder itself needs no token.
|
||||||
- If the engine crashes, its speech server may keep running (and holding ~1 GB) until the app quits.
|
- If the engine crashes, its speech server may keep running (and holding ~1 GB) until the app quits.
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ The built tree has TWO kinds of page, and they need DIFFERENT framing policy:
|
||||||
| **Direct embed** (the product) | `<bundle>/<profile>/index.html`, `<bundle>/<profile>/<instance>/index.html` — the bare map pages the manifest's `iframeUrl` points at | **`*`** — framable on any partner site (that's the whole point) |
|
| **Direct embed** (the product) | `<bundle>/<profile>/index.html`, `<bundle>/<profile>/<instance>/index.html` — the bare map pages the manifest's `iframeUrl` points at | **`*`** — framable on any partner site (that's the whole point) |
|
||||||
| **Staging** (internal preview) | tree root `index.html`, per-bundle `<bundle>/index.html` | **`'self'`** — preview only |
|
| **Staging** (internal preview) | tree root `index.html`, per-bundle `<bundle>/index.html` | **`'self'`** — preview only |
|
||||||
|
|
||||||
The Research Gallery (`doxa-maps-spa/doxa-maps-spa/index.html`) is a direct-embed page like any
|
Deep Research (`doxa-maps-spa/doxa-maps-spa/index.html`) is a direct-embed page like any
|
||||||
other leaf. Its full embed contract (script and iframe) is in
|
other leaf. Its full embed contract (script and iframe) is in
|
||||||
`plugin-designs/doxa-maps-spa/EMBED.md`.
|
`plugin-designs/doxa-maps-spa/EMBED.md`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,15 @@ being duplicated.
|
||||||
|
|
||||||
## The one rule that keeps everything clean
|
## The one rule that keeps everything clean
|
||||||
|
|
||||||
> **Parameterized + genuinely reused by more than one map → the shared library**
|
> **Could serve more than one map → build it in the shared library**, parameterized
|
||||||
> (`library/`, alias `@map`).
|
> (`library/`, alias `@map`).
|
||||||
> **Not reused → it lives in your app-profile folder** (`plugin-designs/<your-map>/`).
|
> **One-off or experimental → it lives in your app-profile folder** (`plugin-designs/<your-map>/`).
|
||||||
|
|
||||||
"**Local by default, promote deliberately.**" When in doubt, keep your change local to your
|
**Reusable by default.** If a component could serve more than one map, build it once in the shared
|
||||||
own map; something graduates into the shared library only once a *second* map genuinely
|
library, driven by props, and land it through the build owner, so other maps adopt it instead of
|
||||||
needs it. Full reasoning — the promotion / orphan-audit rule — is in
|
copying it. A one-off or experimental piece stays in your map's folder. A new pattern starts as a pilot
|
||||||
[`../documentation/explanation.md`](../explanation.md).
|
on one plugin, is approved, and is then rolled out by each owner. The rule in full:
|
||||||
|
[`skills/plugin-designer`](../../skills/plugin-designer/SKILL.md), section 3.
|
||||||
|
|
||||||
## Start here
|
## Start here
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ rsync -a --delete public/dx-maps/ <your-host-checkout>/dx-maps/
|
||||||
it can see and whether it finds itself. To check that what you published is *current*, run
|
it can see and whether it finds itself. To check that what you published is *current*, run
|
||||||
`bun run check:catalog-currency`.
|
`bun run check:catalog-currency`.
|
||||||
|
|
||||||
**Your plugin surfaces itself.** The Research Gallery (`doxa-maps-spa`) reads the built `manifest.json`
|
**Your plugin surfaces itself.** Deep Research (`doxa-maps-spa`) reads the built `manifest.json`
|
||||||
and puts every bundle it doesn't already curate into its folded **Experimental** shelf, with the label and
|
and puts every bundle it doesn't already curate into its folded **Experimental** shelf, with the label and
|
||||||
description from the manifest — no code edit. Promoting it to a curated tab is an optional edit to
|
description from the manifest — no code edit. Promoting it to a curated tab is an optional edit to
|
||||||
`TAB_DEFS` and `NAV_MODEL` in `plugin-designs/doxa-maps-spa/`. One row per bundle: a bundle's extra
|
`TAB_DEFS` and `NAV_MODEL` in `plugin-designs/doxa-maps-spa/`. One row per bundle: a bundle's extra
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ A URL that returns a public token as JSON (`{token|tk|accessToken}`) or as a bar
|
||||||
found; a token baked at build time wins.
|
found; a token baked at build time wins.
|
||||||
- **The studio:** the reader's URL (localStorage). The studio fetches it itself, and the fetched
|
- **The studio:** the reader's URL (localStorage). The studio fetches it itself, and the fetched
|
||||||
token then travels as `tk` / `window.MAP_TOKEN`.
|
token then travels as `tk` / `window.MAP_TOKEN`.
|
||||||
- **Plugins:** none reads `profile-config.tokenUrl` today. The studio and the Research Gallery
|
- **Plugins:** none reads `profile-config.tokenUrl` today. The studio and Deep Research
|
||||||
forward it, but no element consumes it (see the open points below).
|
forward it, but no element consumes it (see the open points below).
|
||||||
|
|
||||||
## 5. People-group list: `'doxa'` | `'unreached'` | `'frontier'` | `'frontier-500k'` | `'unengaged'`
|
## 5. People-group list: `'doxa'` | `'unreached'` | `'frontier'` | `'frontier-500k'` | `'unengaged'`
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ Smallest first. Which bundle is the current example of each: **[reference-capabi
|
||||||
| 2 | **preset-element** (prop-table) | `parameterized` | one profile + a table of named presets; each row is a ready-made map with its own embed page | the bundle ships `<name>.instances.json` — `{ "instances": [{ "id", "title", "props" }] }`; one page per row at `<bundle>/<profile>/<id>/index.html` |
|
| 2 | **preset-element** (prop-table) | `parameterized` | one profile + a table of named presets; each row is a ready-made map with its own embed page | the bundle ships `<name>.instances.json` — `{ "instances": [{ "id", "title", "props" }] }`; one page per row at `<bundle>/<profile>/<id>/index.html` |
|
||||||
| 3 | **multi-view-element** (monolithic) | `monolithic` | one profile holding several screens (tabs or steps), one shown at a time | declared: `<profile>.meta.json` → `{ "type": "monolithic" }` |
|
| 3 | **multi-view-element** (monolithic) | `monolithic` | one profile holding several screens (tabs or steps), one shown at a time | declared: `<profile>.meta.json` → `{ "type": "monolithic" }` |
|
||||||
| 4 | **composite-element** (nested elements) | `nested-elements-mfe` | a profile that places other plugins together and ships the set as one new element | declared: `<profile>.meta.json` → `{ "type": "nested-elements-mfe", "composes": [ … ] }` |
|
| 4 | **composite-element** (nested elements) | `nested-elements-mfe` | a profile that places other plugins together and ships the set as one new element | declared: `<profile>.meta.json` → `{ "type": "nested-elements-mfe", "composes": [ … ] }` |
|
||||||
| 5 | **app-shell** (nested SPAs) | `nested-mfe-spa` | the outer frame — rail, header, navigation — that mounts any of the others; e.g. the Research Gallery (`doxa-maps-spa`) and the Plugin Studio | declared the same way; a compiled Vue custom element like every other rung |
|
| 5 | **app-shell** (nested SPAs) | `nested-mfe-spa` | the outer frame — rail, header, navigation — that mounts any of the others; e.g. Deep Research (`doxa-maps-spa`) and the Plugin Studio | declared the same way; a compiled Vue custom element like every other rung |
|
||||||
|
|
||||||
**Tiers 3–5 are always declared, never guessed** (either spelling; see `TYPE_ALIASES` in
|
**Tiers 3–5 are always declared, never guessed** (either spelling; see `TYPE_ALIASES` in
|
||||||
`internal/plugin-gallery/discover.mjs`). A folder's apparent simplicity does not decide its tier: an
|
`internal/plugin-gallery/discover.mjs`). A folder's apparent simplicity does not decide its tier: an
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ A change here does not affect one map. It ripples to **all** of them. So:
|
||||||
- **Prototyping or experimenting? Don't edit these.** Put your custom, one-off, not-yet-proven component
|
- **Prototyping or experimenting? Don't edit these.** Put your custom, one-off, not-yet-proven component
|
||||||
inside your own map's folder (`plugin-designs/<your-map>/`), where it can be as messy as you need and
|
inside your own map's folder (`plugin-designs/<your-map>/`), where it can be as messy as you need and
|
||||||
breaks nothing else.
|
breaks nothing else.
|
||||||
- **Only proven, parameterized, reusable components graduate into this library.** If a component has hard-coded
|
- **Reusable by default.** If a component could serve more than one map, build it here once, driven by props,
|
||||||
values, assumptions about one specific map, or hasn't been used by more than one map yet — it is **not**
|
and land it through the build owner, so other maps adopt it instead of copying it. If it has hard-coded
|
||||||
ready to live here.
|
values or assumptions about one specific map, it is **not** ready to live here: parameterize it first.
|
||||||
- **A reusable component takes props, not assumptions.** Before you move something in, make it parameterized:
|
- **A reusable component takes props, not assumptions.** Before you move something in, make it parameterized:
|
||||||
the map, the legend, the controls, the search bar all take configuration — yours should too.
|
the map, the legend, the controls, the search bar all take configuration — yours should too.
|
||||||
- **If you must change a shared component, check every map that uses it.** Run `bun run dev` and click through
|
- **If you must change a shared component, check every map that uses it.** Run `bun run dev` and click through
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ without importing each other. This file is the contract they share. It is **docu
|
||||||
exists today**, verified against `development`, not a proposal.
|
exists today**, verified against `development`, not a proposal.
|
||||||
|
|
||||||
The components still live in `plugin-designs/research-dashboard/src/components/dashboards/`. They
|
The components still live in `plugin-designs/research-dashboard/src/components/dashboards/`. They
|
||||||
are deliberately **not** in `library/` yet: a library component with a single consumer is a
|
are not in `library/` yet. Under the repo's "reusable by default" rule
|
||||||
relocation, not a promotion, and the repo has already had to move such modules back. They graduate
|
([`skills/plugin-designer`](../../skills/plugin-designer/SKILL.md), section 3), a component another
|
||||||
when a second dashboard consumes them.
|
dashboard could use belongs in `library/`, driven by props; moving these is a library change for the
|
||||||
|
build owner.
|
||||||
|
|
||||||
## The shape
|
## The shape
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Embedding the Research Gallery
|
# Embedding Deep Research
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
`<doxa-maps-spa>` (labeled **Research Gallery**) is the capability-5 app shell: one element whose
|
`<doxa-maps-spa>` (labeled **Deep Research**) is the capability-5 app shell: one element whose
|
||||||
tab rail nests every production map. It is built to drop onto somebody else's page. Below,
|
tab rail nests every production map. It is built to drop onto somebody else's page. Below,
|
||||||
`TREE` means the URL of the built `doxa-maps/` folder wherever it is served, for example
|
`TREE` means the URL of the built `doxa-maps/` folder wherever it is served, for example
|
||||||
`https://YOUR-HOST/doxa-maps`.
|
`https://YOUR-HOST/doxa-maps`.
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ levels 1 and 2 are detected on their own.
|
||||||
| 2 | preset element (`parameterized`) | one screen, several named presets from `<screen>.instances.json` | `plugin-designs/doxa-simple-map/` |
|
| 2 | preset element (`parameterized`) | one screen, several named presets from `<screen>.instances.json` | `plugin-designs/doxa-simple-map/` |
|
||||||
| 3 | multi-view element (`monolithic`) | many views fused inside one element | `plugin-designs/doxa-research-map/` |
|
| 3 | multi-view element (`monolithic`) | many views fused inside one element | `plugin-designs/doxa-research-map/` |
|
||||||
| 4 | composite element (`nested-elements-mfe`) | nests other elements, each still embeddable alone, wired by props and events | `plugin-designs/dashboard-plus-grid/` (the Big Picture tab) |
|
| 4 | composite element (`nested-elements-mfe`) | nests other elements, each still embeddable alone, wired by props and events | `plugin-designs/dashboard-plus-grid/` (the Big Picture tab) |
|
||||||
| 5 | app shell (`nested-mfe-spa`) | nests whole apps | `plugin-designs/doxa-maps-spa/` (the Research Gallery) |
|
| 5 | app shell (`nested-mfe-spa`) | nests whole apps | `plugin-designs/doxa-maps-spa/` (Deep Research) |
|
||||||
|
|
||||||
**Your declaration is checked, not merely trusted.** `internal/check-capability-derived.mjs`
|
**Your declaration is checked, not merely trusted.** `internal/check-capability-derived.mjs`
|
||||||
derives the level from what your plugin actually `composes` and fails when an explicit `"type"`
|
derives the level from what your plugin actually `composes` and fails when an explicit `"type"`
|
||||||
|
|
@ -221,7 +221,7 @@ line number, because lines move.
|
||||||
| Interop: one element reacts to another's events | Simple Research: `plugin-designs/research-map-plus-grid/research-map-plus-grid.vue` | the map listening for the grid's `groups-filtered` event |
|
| Interop: one element reacts to another's events | Simple Research: `plugin-designs/research-map-plus-grid/research-map-plus-grid.vue` | the map listening for the grid's `groups-filtered` event |
|
||||||
| Composite element (capability 4) | Big Picture: `plugin-designs/dashboard-plus-grid/dashboard-plus-grid.meta.json` | `"composes"`: two elements, each still embeddable alone |
|
| Composite element (capability 4) | Big Picture: `plugin-designs/dashboard-plus-grid/dashboard-plus-grid.meta.json` | `"composes"`: two elements, each still embeddable alone |
|
||||||
| One bundle, several embeddable screens | UPG-100: `plugin-designs/my-upg-100-list/` | `upg-100-mfe`, `upg-100-list` and `poster-wall` from one bundle |
|
| One bundle, several embeddable screens | UPG-100: `plugin-designs/my-upg-100-list/` | `upg-100-mfe`, `upg-100-list` and `poster-wall` from one bundle |
|
||||||
| App shell (capability 5) | Research Gallery: `plugin-designs/doxa-maps-spa/doxa-maps-spa.vue` | every plugin as a tab, filled from the manifest |
|
| App shell (capability 5) | Deep Research: `plugin-designs/doxa-maps-spa/doxa-maps-spa.vue` | every plugin as a tab, filled from the manifest |
|
||||||
|
|
||||||
`emissivePaint` and `labelFont` (section 5) have no production-plugin exemplar, because the
|
`emissivePaint` and `labelFont` (section 5) have no production-plugin exemplar, because the
|
||||||
production plugins get them through the library's own layers. The starter uses both directly:
|
production plugins get them through the library's own layers. The starter uses both directly:
|
||||||
|
|
@ -258,7 +258,7 @@ tag from any host), the **mobile app** (the same folder wrapped by Capacitor, `b
|
||||||
the **desktop app** (the same folder in Tauri, `bun run tauri:build`, a proof of concept).
|
the **desktop app** (the same folder in Tauri, `bun run tauri:build`, a proof of concept).
|
||||||
|
|
||||||
**Your plugin runs everywhere unless you say otherwise.** A `<profile>.meta.json` `"targets"` list
|
**Your plugin runs everywhere unless you say otherwise.** A `<profile>.meta.json` `"targets"` list
|
||||||
narrows that, and it is read, not decorative: the Research Gallery skips a bundle that does not
|
narrows that, and it is read, not decorative: Deep Research skips a bundle that does not
|
||||||
list `web` (`plugin-designs/doxa-maps-spa/doxa-maps-spa.vue:605`). Declare it only for a plugin
|
list `web` (`plugin-designs/doxa-maps-spa/doxa-maps-spa.vue:605`). Declare it only for a plugin
|
||||||
that genuinely cannot work in a plain web embed — Rudder needs a local speech engine. Details:
|
that genuinely cannot work in a plain web embed — Rudder needs a local speech engine. Details:
|
||||||
`references/targets.md`.
|
`references/targets.md`.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ A plugin that needs one names it in its `<profile>.meta.json` `"backend"` key, a
|
||||||
`plugin-designs/rudder-voice/rudder-voice.meta.json` does with `"backend": "backend/rudder-engine"`.
|
`plugin-designs/rudder-voice/rudder-voice.meta.json` does with `"backend": "backend/rudder-engine"`.
|
||||||
|
|
||||||
A plugin that needs a local backend almost certainly also needs `"targets"` without `web`, which
|
A plugin that needs a local backend almost certainly also needs `"targets"` without `web`, which
|
||||||
keeps it out of the Research Gallery — see `targets.md`. Rudder declares both.
|
keeps it out of Deep Research — see `targets.md`. Rudder declares both.
|
||||||
|
|
||||||
## The database rule: schema is a commit, never a click
|
## The database rule: schema is a commit, never a click
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ a widget target without a corner (or a corner without the target), and a `backen
|
||||||
|
|
||||||
- `internal/profile-meta.mjs:28` reads the field (string entries only) and `:36` carries it into
|
- `internal/profile-meta.mjs:28` reads the field (string entries only) and `:36` carries it into
|
||||||
the manifest, so every consumer of the manifest sees it.
|
the manifest, so every consumer of the manifest sees it.
|
||||||
- **The Research Gallery skips a bundle whose every profile is a widget or lacks the `web`
|
- **Deep Research skips a bundle whose every profile is a widget or lacks the `web`
|
||||||
target** — `plugin-designs/doxa-maps-spa/doxa-maps-spa.vue:605`:
|
target** — `plugin-designs/doxa-maps-spa/doxa-maps-spa.vue:605`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue