You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 8600b67
Browse filesBrowse the repository at this point in the historyBrowse files
Adopts antfu's review on the Terms page: the hub UI implementation term
becomes "hub UI provider" repo-wide ("external viewer" survives for
cross-origin surfaces and gains its own terms row), the mount-context
row reads "hosted / standalone adapters", and the in-page channel lists
MessageChannel alongside BroadcastChannel. Diagnostic fix strings and
code comments follow; API names (initHub's ui.viewer slot,
registerDevframeViewerOrigin) are unchanged.
Copy file name to clipboardExpand all lines: AGENTS.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,9 +2,9 @@
2
2
3
3
## Positioning
4
4
5
-
**`devframe`** is the framework-neutral container for one devtool integration, portable across viewers. Build a single tool (its RPC, its SPA, its diagnostics, its CLI/build/embedded outputs) without caring how it'll be displayed. A devframe runs standalone (CLI, static deploy, embedded SPA) just as well as it mounts inside a hub.
5
+
**`devframe`** is the framework-neutral container for one devtool integration, portable across hub UI providers. Build a single tool (its RPC, its SPA, its diagnostics, its CLI/build/embedded outputs) without caring how it'll be displayed. A devframe runs standalone (CLI, static deploy, embedded SPA) just as well as it mounts inside a hub.
6
6
7
-
**`@devframes/hub`** is the framework-neutral hub layer that sits on top of devframe and provides the multi-devframe orchestration (docks, terminals, messages, commands). It does not ship UI - viewers (e.g. `@vitejs/devtools-kit`) provide their own UI on top of the hub's RPC + shared-state protocol. It does ship a **headless client runtime** (`createDevframeClientHost()` from `@devframes/hub/client`): booted in the host page, it assembles the shared `DevframeClientContext` (panel, docks, commands, when) and imports each dock entry's client script (`action` / `custom-render` / iframe `clientScript`) into that page - how a built-in devframe like the a11y inspector runs its page script inside the user app's page. See `examples/hub-vite/` for a working ~120-line Vite host demonstrating the protocol end to end.
7
+
**`@devframes/hub`** is the framework-neutral hub layer that sits on top of devframe and provides the multi-devframe orchestration (docks, terminals, messages, commands). It does not ship UI - hub UI providers (e.g. `@vitejs/devtools-kit`) provide their own UI on top of the hub's RPC + shared-state protocol. It does ship a **headless client runtime** (`createDevframeClientHost()` from `@devframes/hub/client`): booted in the host page, it assembles the shared `DevframeClientContext` (panel, docks, commands, when) and imports each dock entry's client script (`action` / `custom-render` / iframe `clientScript`) into that page - how a built-in devframe like the a11y inspector runs its page script inside the user app's page. See `examples/hub-vite/` for a working ~120-line Vite host demonstrating the protocol end to end.
8
8
9
9
## Terminology
10
10
@@ -15,7 +15,7 @@ The docs' canonical vocabulary lives in [`docs/content/1.guide/1.terms.md`](docs
15
15
-**host framework** is the environment a devframe or hub mounts into (a Vite dev server, a Next.js app, a Hono server); named forms like "the Vite host" are fine. **host page** is the browser document where the client runtime boots; **user app** is the application being developed and inspected.
16
16
- A devframe's two halves are the **node side** and the **browser side**.
17
17
- Browser-side terms: **client runtime** (`createDevframeClientHost()`), **client context**, **client script**, **page script** (a devframe's script in the user app's page - never "agent"; **coding agent** is the only agent), **RPC client** (`connectDevframe()`), **SPA**, **panel** (a devframe's SPA as a rendered surface), **surface** (any rendered browser view - say "API", not "API surface").
- Hub terms: **hub UI provider** (a hub UI implementation - never "shell" or bare "viewer"; "external viewer" stays for cross-origin surfaces in the security docs), **dock entry** / **dock rail** / **dock panel**, **mounted devframe** (never "frame").
19
19
- The three communication paths: **RPC** (browser side ↔ node side), the **client context** (client scripts ↔ client runtime), and the **in-page channel** (page script ↔ panel, same-origin in-browser).
20
20
- Storage scopes: **workspace scope** (committable, per-repo), **project scope** (per-checkout), **global scope** (per-user) - never describe the project scope as "per-workspace".
21
21
-**framework kits** are `@devframes/vite` / `@devframes/nuxt` / `@devframes/next`; refer to external products by their full names (`@vitejs/devtools-kit`, `@nuxt/devtools`).
@@ -72,8 +72,8 @@ The framework kits - `@devframes/vite`, `@devframes/nuxt`, `@devframes/next` - e
72
72
-**`.../single`** - **build & dev-serve a single devframe's SPA** with that tool (the "I'm authoring one devframe" scope). Vite: the `devframeVitePlugin` / `devframeViteBridge` / `devframeVite` plugins. Next: `withDevframe` + `createDevframeNextHandler`, with its React client at `.../single/client`. Nuxt: the Nuxt module (registered as `modules: ['@devframes/nuxt/single']`).
73
73
-**`.../hub`** - **mount a whole `@devframes/hub` (many devframes) inside that tool** (the "I'm standing up devtools" scope). Wraps `initHub`, defaults the UI slot to `@devframes/hub-ui`'s `createUi()` (overridable via `ui`, or `ui: false` for headless), and ships a browser client helper at `.../hub/client` (a thin, lifecycle-managing wrapper over `@devframes/hub/client`'s `createDevframeClientHost`). `@devframes/hub` and `@devframes/hub-ui` are **optional peers** of these packages; `hub-ui` is loaded lazily (a bundler-ignored dynamic `import()` in the Next hub) so it stays optional and its `import.meta.url` asset lookups resolve at request time.
74
74
-**The bare root (`.`) throws** a helpful error pointing at the two subpaths - never put real code on it.
75
-
-**Vite and Nuxt already have native hub viewers** (`@vitejs/devtools-kit`, `@nuxt/devtools`), so `@devframes/vite/hub` and `@devframes/nuxt/hub` still work but emit a one-time `console.warn` recommending those (silence with `{ quiet: true }`). `@devframes/next/hub` has no native counterpart, so it warns nothing.
76
-
- The **full hub examples** (`examples/hub-vite`, `examples/hub-next`) consume `.../hub` on the node side but keep hand-rolling their own viewer against `@devframes/hub/client` with `ui: false` - that hand-rolled viewer is the whole point of those reference hosts. The **minimal** ones (`examples/hub-*-minimal`) consume `.../hub` with the default `@devframes/hub-ui` and inject its `embedded.js`, needing no browser-side code.
75
+
-**Vite and Nuxt already have native hub UI providers** (`@vitejs/devtools-kit`, `@nuxt/devtools`), so `@devframes/vite/hub` and `@devframes/nuxt/hub` still work but emit a one-time `console.warn` recommending those (silence with `{ quiet: true }`). `@devframes/next/hub` has no native counterpart, so it warns nothing.
76
+
- The **full hub examples** (`examples/hub-vite`, `examples/hub-next`) consume `.../hub` on the node side but keep hand-rolling their own hub UI provider against `@devframes/hub/client` with `ui: false` - that hand-rolled hub UI provider is the whole point of those reference hosts. The **minimal** ones (`examples/hub-*-minimal`) consume `.../hub` with the default `@devframes/hub-ui` and inject its `embedded.js`, needing no browser-side code.
77
77
78
78
### Design system
79
79
@@ -95,7 +95,7 @@ All five built-in plugins - and every example under `examples/` - share one desi
95
95
96
96
### Devframe design principles
97
97
98
-
These reinforce devframe's positioning as "the container for one devtool integration, portable to multiple viewers". When in doubt, err on the side of "devframe provides primitives, the hub provides UX".
98
+
These reinforce devframe's positioning as "the container for one devtool integration, portable to multiple hub UI providers". When in doubt, err on the side of "devframe provides primitives, the hub provides UX".
99
99
100
100
-**Single-integration scope.** Devframe describes one tool. If a feature only makes sense when multiple tools share a UI - docking, a unified command palette, cross-tool toasts, terminal aggregation - it belongs in a hub package, not here.
101
101
-**Headless by default.** No default startup banners, no opinionated logging to stdout, no default styling. Provide hooks (`onReady`, `cli.configure`, etc.); let the application print its own branding. Structured diagnostics via `nostics` are fine - ad-hoc `console.log`s baked into adapters are not.
Copy file name to clipboardExpand all lines: docs/content/1.guide/1.terms.md
+4-3Lines changed: 4 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,7 @@ Every concept in these docs has exactly one name. This page fixes that vocabular
17
17
|**framework kit**| Framework conventions over the standard handler, each split into a `/single` and a `/hub` scope. |`@devframes/vite`, `@devframes/nuxt`, `@devframes/next`|
18
18
|**opt-in package**| A capability shipped as its own package and added when needed. |`@devframes/json-render`|
19
19
|**hub**| The composition layer that puts many devframes behind one handler; *a hub* is one `initHub()` instance. |`@devframes/hub`, `initHub()`|
20
-
|**viewer**| A hub UI implementation: the node-side `ui` slot plus the browser-side context contract. `@devframes/hub-ui` is the reference viewer. |`initHub({ ui })`|
20
+
|**hub UI provider**| A hub UI implementation: the node-side `ui` slot plus the browser-side context contract. `@devframes/hub-ui` is the reference hub UI provider. |`initHub({ ui })`|
21
21
22
22
## Node side
23
23
@@ -29,7 +29,7 @@ A devframe has two halves: the **node side** registers RPC functions and owns st
29
29
|**host framework**| The environment a devframe or hub mounts into: a Vite dev server, a Next.js app, a Hono server. Named forms — *the Vite host*, *a Next.js host* — refer to a specific one. |`DevframeHost`|
30
30
|**dev server**| The standalone HTTP server the dev adapter starts. |`createDevServer()`|
31
31
|**side-car server**| The separate RPC/WebSocket process used when a host framework's handlers never see upgrade requests. | — |
32
-
|**hosted / standalone**| The two mount contexts: hosted adapters (vite, embedded) default the base path to `/__<id>/`; standalone adapters (cli, build) default to `/`. |`resolveBasePath()`|
32
+
|**hosted / standalone adapters**| The two mount contexts: hosted adapters (vite, embedded) default the base path to `/__<id>/`; standalone adapters (cli, build) default to `/`. |`resolveBasePath()`|
@@ -49,6 +49,7 @@ A devframe has two halves: the **node side** registers RPC functions and owns st
49
49
|**SPA**| A devframe's built web interface; `clientAssets` says where it lives. |`clientAssets`|
50
50
|**panel**| A devframe's SPA as a rendered surface — in a dock panel or standalone. | — |
51
51
|**surface**| Any rendered browser view: a panel, a dock iframe, a standalone SPA. | — |
52
+
|**external viewer**| A cross-origin surface (a browser extension, a separate devtools page) connecting from its own origin. |`registerDevframeViewerOrigin()`|
52
53
|**coding agent**| An agent consuming a devframe over MCP — the only agent in these docs. |`createMcpServer()`|
53
54
54
55
## Hub
@@ -68,4 +69,4 @@ Three distinct paths connect the pieces; each has its own name.
68
69
|------|---------|-----------|
69
70
|**RPC**| browser side ↔ node side | WebSocket or static snapshot, via `connectDevframe()`|
70
71
|**client context**| client scripts ↔ client runtime | a shared object inside the host page |
// Already wired to the local dev server via the injected descriptor.
241
241
```
242
242
243
-
The descriptor's session-only, pre-approved token makes `ensureTrusted()` resolve immediately. An external hub builds a viewer URL from a trusted connection with `buildRemoteDevframeUrl()`, keeping the token in the URL fragment:
243
+
The descriptor's session-only, pre-approved token makes `ensureTrusted()` resolve immediately. An external hub builds an external-viewer URL from a trusted connection with `buildRemoteDevframeUrl()`, keeping the token in the URL fragment:
244
244
245
245
```ts
246
246
import {
@@ -352,4 +352,4 @@ async function reconnect() {
352
352
}
353
353
```
354
354
355
-
In a hub, a viewer reads this status from [`context.connection`](/guide/client-context#the-client-context).
355
+
In a hub, a hub UI provider reads this status from [`context.connection`](/guide/client-context#the-client-context).
Copy file name to clipboardExpand all lines: docs/content/1.guide/17.hub.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,9 @@
1
1
---
2
2
title: 'Hub'
3
-
description: '@devframes/hub orchestrates many devtools sharing a UI: a dock registry, terminal aggregation, message/toast queue, and command palette. It ships no UI — viewers provide their own atop the hub''s RPC + shared-state protocol.'
3
+
description: '@devframes/hub orchestrates many devtools sharing a UI: a dock registry, terminal aggregation, message/toast queue, and command palette. It ships no UI — hub UI providers provide their own atop the hub''s RPC + shared-state protocol.'
4
4
---
5
5
6
-
`@devframes/hub` orchestrates many devtools sharing a UI: a dock registry, terminal aggregation, message/toast queue, and command palette. It ships no UI — viewers provide their own atop the hub's RPC + shared-state protocol.
6
+
`@devframes/hub` orchestrates many devtools sharing a UI: a dock registry, terminal aggregation, message/toast queue, and command palette. It ships no UI — hub UI providers provide their own atop the hub's RPC + shared-state protocol.
7
7
8
8

9
9
@@ -71,7 +71,7 @@ A `type: 'launcher'` dock entry is a one-click action tile. Three optional `laun
71
71
72
72
| Field | Purpose |
73
73
|---|---|
74
-
|`command`| Bound command id; out-of-process viewers dispatch via `hub:commands:execute` (register a handler via `ctx.commands`). |
74
+
|`command`| Bound command id; out-of-process hub UI providers dispatch via `hub:commands:execute` (register a handler via `ctx.commands`). |
75
75
|`terminalSessionId`| Tracked session id; a "view in terminal" action calls `hub:docks:activate` with the terminals dock id and `{ sessionId }`. |
76
76
|`digest`| Latest progress line, shown inline; patch via `docks.update()`. |
Copy file name to clipboardExpand all lines: docs/content/1.guide/18.client-context.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -83,7 +83,7 @@ For a URL, attach it via `ctx.install(myDevframe, { dock: { clientScript: { impo
83
83
84
84
### Bare npm specifiers
85
85
86
-
Resolving a bare specifier is the **host framework's capability**: a host framework advertises a resolution template at `ConnectionMeta.configs.dock.clientModuleResolution` (loaders replace `{specifier}` before import). A Vite host declares this by default (`@devframes/vite/hub`) as `initHub({ clientModuleResolution: '/@id/{specifier}' })`; then use the specifier alone as `importFrom`. A host framework with no template (Next.js) supports the URL shape only, warning [`DF8111`](/errors/DF8111) on a specifier. A viewer can override with `createDevframeClientHost({ resolveClientModule })`.
86
+
Resolving a bare specifier is the **host framework's capability**: a host framework advertises a resolution template at `ConnectionMeta.configs.dock.clientModuleResolution` (loaders replace `{specifier}` before import). A Vite host declares this by default (`@devframes/vite/hub`) as `initHub({ clientModuleResolution: '/@id/{specifier}' })`; then use the specifier alone as `importFrom`. A host framework with no template (Next.js) supports the URL shape only, warning [`DF8111`](/errors/DF8111) on a specifier. A hub UI provider can override with `createDevframeClientHost({ resolveClientModule })`.
87
87
88
88
Client scripts execute in the user app's page realm (`window`); anchor shared state on `globalThis`.
89
89
@@ -103,10 +103,10 @@ A tool with many internal views (Nuxt DevTools' tabs) can surface each as a hub
103
103
|---|---|---|
104
104
|`ready` / `manifest`| iframe → host page | tab list (`{ tabs, current }`), on load and change |
105
105
|`navigate`| host page → iframe | show a view (`{ tabId, navTarget }`); the SPA routes client-side |
106
-
|`navigated`| iframe → host page | the SPA navigated internally; the viewer highlights the dock |
106
+
|`navigated`| iframe → host page | the SPA navigated internally; the hub UI provider highlights the dock |
107
107
108
108
It materializes a [client-only dock](#client-only-docks) per tab (id `<frameId>:<tabId>`) sharing the anchor's `frameId` and a `navTarget`, independent of [`groupId`](/guide/hub#grouping-dock-entries).
109
109
110
-
### The viewer's part
110
+
### The hub UI provider's part
111
111
112
-
A viewer keeps one iframe alive per `frameId` (shown/hidden); on mount, it sets the element on the anchor's `docks.getStateById(anchorId)` state (`domElements.iframe`) and emits `dom:iframe:mounted`. See the "Tabbed Tool" in [`examples/hub-vite`](https://github.com/devframes/devframe/tree/main/examples/hub-vite) / [`hub-next`](https://github.com/devframes/devframe/tree/main/examples/hub-next).
112
+
A hub UI provider keeps one iframe alive per `frameId` (shown/hidden); on mount, it sets the element on the anchor's `docks.getStateById(anchorId)` state (`domElements.iframe`) and emits `dom:iframe:mounted`. See the "Tabbed Tool" in [`examples/hub-vite`](https://github.com/devframes/devframe/tree/main/examples/hub-vite) / [`hub-next`](https://github.com/devframes/devframe/tree/main/examples/hub-next).
`@devframes/hub-ui`'s `createUi()` is the reference (viewer + floating dock); its `setup(ctx)` publishes config to `ctx.staticConfig.ui` (`ConnectionMeta.configs.ui`):
60
+
`@devframes/hub-ui`'s `createUi()` is the reference (standalone `viewer` SPA + floating dock); its `setup(ctx)` publishes config to `ctx.staticConfig.ui` (`ConnectionMeta.configs.ui`):
61
61
62
62
-**`branding`** — rebrand the UI (logo, name, primary color).
A renderer registered at boot (`createDevframeClientHost({ renderers })`) overrides the manifest; an uncovered type shows the viewer's missing-renderer fallback.
83
+
A renderer registered at boot (`createDevframeClientHost({ renderers })`) overrides the manifest; an uncovered type shows the hub UI provider's missing-renderer fallback.
84
84
85
85
Registrations are validated fail-fast: one module per type (`DF8108`), an existing bundle (`DF8109`), a route-safe type name (`DF8110`).
0 commit comments