Skip to content

Commit f88a023

Browse files
committed
docs: add a canonical Terms page and terminology rules, renumber the guide
One name per concept: a new guide-leading Terms page fixes the vocabulary (a devframe, built-in devframe, host framework, host page, user app, node side / browser side, client runtime, page script, in-page channel, viewer, dock entry/rail/panel, storage scopes), AGENTS.md gains the matching regulation, and the guide pages shift up one number to lead with it. Stale numbered-path comments in code follow the renumber.
1 parent 9649672 commit f88a023

39 files changed

Lines changed: 368 additions & 282 deletions

AGENTS.md

Lines changed: 26 additions & 11 deletions
Large diffs are not rendered by default.

docs/content/1.guide/1.terms.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: 'Terms'
3+
description: 'The canonical vocabulary of these docs: one name per concept, the API or package that anchors it, and how the pieces talk to each other.'
4+
---
5+
6+
Every concept in these docs has exactly one name. This page fixes that vocabulary — when a term below appears anywhere in the documentation, it carries the meaning defined here.
7+
8+
## Core
9+
10+
| Term | Meaning | Anchor |
11+
|------|---------|--------|
12+
| **Devframe** | The product: a framework-neutral foundation for building a devtool once and running it everywhere. ||
13+
| `devframe` | The npm package the foundation ships as. | `devframe` |
14+
| **a devframe** | One tool: a definition plus its SPA, mountable anywhere. | `defineDevframe()`, `DevframeDefinition` |
15+
| **built-in devframe** | A ready-to-run devframe shipped from this repo (data inspector, inspect, OG, a11y, git, terminals, code-server, assets). The `plugin-` npm prefix only sets these packages apart from core packages — Devframe has no plugin concept. | `@devframes/plugin-*` |
16+
| **adapter** | A deployment entry point under `devframe/adapters/*`: cli (cac), dev, build, vite, embedded, mcp. | `devframe/adapters/*` |
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+
| **opt-in package** | A capability shipped as its own package and added when needed. | `@devframes/json-render` |
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 })` |
21+
22+
## Node side
23+
24+
A devframe has two halves: the **node side** registers RPC functions and owns state; the **browser side** renders and calls them.
25+
26+
| Term | Meaning | Anchor |
27+
|------|---------|--------|
28+
| **node side** | The half of a devframe running in the Node process. | `setup(ctx)` |
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+
| **dev server** | The standalone HTTP server the dev adapter starts. | `createDevServer()` |
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()` |
33+
| **workspace scope** | Committable per-repository storage. | `DevframeStorageScope` |
34+
| **project scope** | Per-checkout storage, gitignored. | `DevframeStorageScope` |
35+
| **global scope** | Per-user storage. | `DevframeStorageScope` |
36+
37+
## Browser side
38+
39+
| Term | Meaning | Anchor |
40+
|------|---------|--------|
41+
| **browser side** | The half of a devframe running in a page. | `devframe/client` |
42+
| **user app** | The application being developed and inspected. ||
43+
| **host page** | The browser document where the client runtime boots — in dev, usually the user app's own page. ||
44+
| **client runtime** | The headless runtime booted once per host page: it connects RPC, assembles the client context, and imports client scripts. | `createDevframeClientHost()` |
45+
| **client context** | The shared object client scripts receive: panel, docks, commands, when-clauses. | `DevframeClientContext` |
46+
| **client script** | A dock entry's script, imported into the host page by the client runtime. | `clientScript` |
47+
| **page script** | A devframe's script running in the user app's page — loaded as a client script or standalone. The a11y page script runs axe-core. ||
48+
| **RPC client** | The typed connection a browser surface gets. | `connectDevframe()` |
49+
| **SPA** | A devframe's built web interface; `clientAssets` says where it lives. | `clientAssets` |
50+
| **panel** | A devframe's SPA as a rendered surface — in a dock panel or standalone. ||
51+
| **surface** | Any rendered browser view: a panel, a dock iframe, a standalone SPA. ||
52+
| **coding agent** | An agent consuming a devframe over MCP — the only agent in these docs. | `createMcpServer()` |
53+
54+
## Hub
55+
56+
| Term | Meaning | Anchor |
57+
|------|---------|--------|
58+
| **mounted devframe** | A devframe served inside a hub under `<base><id>/`. | `initHub({ devframes })` |
59+
| **dock entry** | A registry item: iframe, launcher, custom-render, group, or json-render. | `ctx.docks` |
60+
| **dock rail** | The bar listing every mounted tool. ||
61+
| **dock panel** | The open drawer rendering the active dock entry. ||
62+
63+
## Communication paths
64+
65+
Three distinct paths connect the pieces; each has its own name.
66+
67+
| Path | Between | Transport |
68+
|------|---------|-----------|
69+
| **RPC** | browser side ↔ node side | WebSocket or static snapshot, via `connectDevframe()` |
70+
| **client context** | client scripts ↔ client runtime | a shared object inside the host page |
71+
| **in-page channel** | page script ↔ panel | same-origin, entirely in-browser (e.g. a `BroadcastChannel`) |
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description: 'ctx.diagnostics is a thin layer over nostics for author-defined co
77

88
| Surface | Purpose | Example |
99
|---------|---------|---------|
10-
| `ctx.diagnostics` | Coded errors and warnings emitted from node-side plugin code | `MYP0001: Plugin foo not configured` |
10+
| `ctx.diagnostics` | Coded errors and warnings emitted from node-side code | `MYP0001: Plugin foo not configured` |
1111
| [`ctx.messages`](https://devtools.vite.dev/kit/messages) | Free-form, user-facing notifications shown in the Messages panel | `'Audit complete — 3 issues found'` |
1212

1313
## Shape
@@ -20,12 +20,12 @@ interface DevframeDiagnosticsHost {
2020
/** Register additional diagnostic definitions. */
2121
register: (definitions: Record<string, unknown>) => void
2222

23-
/** Build a typed diagnostics object with the host's ANSI reporter pre-wired. */
23+
/** Build a typed diagnostics object with devframe's ANSI reporter pre-wired. */
2424
defineDiagnostics: typeof defineDiagnostics
2525
}
2626
```
2727

28-
The host ships pre-seeded with devframe's `DF*` codes plus the host package's (`DTK*`, etc.); call `register()` to add your own.
28+
The diagnostics host ships pre-seeded with devframe's `DF*` codes plus the host framework's own (`DTK*`, etc.); call `register()` to add your own.
2929

3030
## Register your own codes
3131

@@ -50,7 +50,7 @@ export function MyPlugin(): PluginWithDevTools {
5050

5151
ctx.diagnostics.register(myDiagnostics)
5252

53-
// Emit through the host's shared reporter:
53+
// Emit through the host framework's shared reporter:
5454
myDiagnostics.MYP0002()
5555
},
5656
},
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
title: 'When Clauses'
3-
description: 'When clauses gate visibility and executability of docks, commands, and UI surfaces via VS Code''s when-clause contexts. The evaluator whenexpr re-exports at devframe/utils/when.'
3+
description: 'When clauses gate visibility and executability of docks, commands, and custom UI via VS Code''s when-clause contexts. The evaluator whenexpr re-exports at devframe/utils/when.'
44
---
55

6-
When clauses gate visibility and executability of docks, commands, and UI surfaces via [VS Code's when-clause contexts](https://code.visualstudio.com/api/references/when-clause-contexts). The evaluator [`whenexpr`](https://github.com/antfu/whenexpr) re-exports at `devframe/utils/when`.
6+
When clauses gate visibility and executability of docks, commands, and custom UI via [VS Code's when-clause contexts](https://code.visualstudio.com/api/references/when-clause-contexts). The evaluator [`whenexpr`](https://github.com/antfu/whenexpr) re-exports at `devframe/utils/when`.
77

88
## Usage
99

@@ -22,7 +22,7 @@ ctx.commands.register({
2222

2323
### On dock entries
2424

25-
Gates dock-bar visibility.
25+
Gates dock-rail visibility.
2626

2727
```ts
2828
ctx.docks.register({
@@ -37,7 +37,7 @@ ctx.docks.register({
3737

3838
### Render-only visibility on dock entries
3939

40-
A dock entry also takes `visibility`, a second expression that hides only its dock-bar button while keeping the entry registered and reachable (e.g. a `subTabs` anchor).
40+
A dock entry also takes `visibility`, a second expression that hides only its dock-rail button while keeping the entry registered and reachable (e.g. a `subTabs` anchor).
4141

4242
```ts
4343
ctx.docks.register({
@@ -89,21 +89,21 @@ when: 'false' // never visible
8989
when: 'clientType == embedded' // only embedded
9090
when: 'dockOpen && !paletteOpen' // dock open and palette closed
9191
when: '(clientType == embedded && dockOpen) || clientType == standalone'
92-
when: 'my-devtool.ready' // custom plugin context
92+
when: 'my-devtool.ready' // custom devframe context
9393
```
9494

9595
## Built-in context variables
9696

9797
| Variable | Type | Description |
9898
|----------|------|-------------|
99-
| `clientType` | `'embedded' \| 'standalone'` | `embedded` in the host overlay, `standalone` in a separate window. |
99+
| `clientType` | `'embedded' \| 'standalone'` | `embedded` in the host page's overlay, `standalone` in a separate window. |
100100
| `dockOpen` | `boolean` | Dock panel open. |
101101
| `paletteOpen` | `boolean` | Command palette open. |
102102
| `dockSelectedId` | `string` | Selected dock entry ID; `''` if none. |
103103

104104
## Namespaced context keys
105105

106-
Plugins add keys with `.` or `:`:
106+
Devframes add keys with `.` or `:`:
107107

108108
```ts
109109
context['my-devtool.ready'] = true
@@ -144,9 +144,9 @@ defineCommand({
144144
})
145145
```
146146

147-
### Key validation with plugin contexts
147+
### Key validation with devframe contexts
148148

149-
The default `WhenContext` leaves plugin keys open-ended (`[key: string]: unknown`). To validate names, declare a narrower context and wrapper:
149+
The default `WhenContext` leaves devframe keys open-ended (`[key: string]: unknown`). To validate names, declare a narrower context and wrapper:
150150

151151
```ts
152152
import type { WhenContext, WhenExpression } from 'devframe/utils/when'
@@ -214,4 +214,4 @@ Returns one (possibly namespaced) key's value.
214214

215215
### `WhenExpression<Ctx, S>`
216216

217-
The branded `whenexpr` expression type for typed `define*` helpers ([above](#key-validation-with-plugin-contexts)).
217+
The branded `whenexpr` expression type for typed `define*` helpers ([above](#key-validation-with-devframe-contexts)).
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ defineDevframe({
131131

132132
Call `connectDevframe()` in a Client Component — see [Client](/guide/client) and [`examples/next-runtime-snapshot`](https://github.com/devframes/devframe/tree/main/examples/next-runtime-snapshot).
133133

134-
## Connecting from the client
134+
## Connecting from the browser side
135135

136136
With the Nuxt helper, use `$rpc`:
137137

@@ -207,7 +207,7 @@ It's the no-args fallback for any deployed `rpc.call('my-tool:get-payload', …)
207207

208208
## On-disk caching
209209

210-
Persistence is the app's job ([`unstorage`](https://unstorage.unjs.io/) recommended); keep cache paths under `node_modules/.cache/<your-devtool-id>/` to rotate with `pnpm install`.
210+
Persistence is your tool's job ([`unstorage`](https://unstorage.unjs.io/) recommended); keep cache paths under `node_modules/.cache/<your-devtool-id>/` to rotate with `pnpm install`.
211211

212212
```ts
213213
import { resolve } from 'pathe'
@@ -238,7 +238,7 @@ defineDevframe({
238238

239239
## Live-reload on config changes
240240

241-
Filesystem watching is the app's job — wire chokidar, signal the client via shared state.
241+
Filesystem watching is your tool's job — wire chokidar, signal the browser side via shared state.
242242

243243
```ts [src/cli.ts]
244244
defineDevframe({
@@ -267,7 +267,7 @@ defineDevframe({
267267
})
268268
```
269269

270-
On the client:
270+
On the browser side:
271271

272272
```ts
273273
const my = (await connectDevframe()).scope('my-tool')
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
title: 'Client'
3-
description: 'The browser client connects any surface — dock iframe, remote page, standalone SPA — to the Devframe server with type-safe RPC, shared state, and a trust handshake.'
3+
description: 'The RPC client connects any surface — dock iframe, remote page, standalone SPA — to a devframe''s node side with type-safe RPC, shared state, and a trust handshake.'
44
---
55

6-
The browser client connects any surface — dock iframe, remote page, standalone SPA — to the Devframe server with type-safe RPC, shared state, and a trust handshake.
6+
The RPC client connects any surface — dock iframe, remote page, standalone SPA — to a devframe's node side with type-safe RPC, shared state, and a trust handshake.
77

88
## Connecting
99

@@ -43,9 +43,9 @@ import { connectDevframe } from 'devframe/client'
4343
const rpc = await connectDevframe({ connection })
4444
```
4545

46-
The client retains it as `rpc.connection`; cross-realm viewers read it via `getDevframeConnection()` or `DEVFRAME_CONNECTION_KEY` (`devframe/constants`).
46+
The RPC client retains it as `rpc.connection`; cross-realm viewers read it via `getDevframeConnection()` or `DEVFRAME_CONNECTION_KEY` (`devframe/constants`).
4747

48-
An external viewer registers its origin before the WebSocket opens (needs `viewerOriginToken` in the host's connection metadata; see [External viewer origins](/guide/security#external-viewer-origins)):
48+
An external viewer registers its origin before the WebSocket opens (needs `viewerOriginToken` in the host framework's connection metadata; see [External viewer origins](/guide/security#external-viewer-origins)):
4949

5050
```ts
5151
import { registerDevframeViewerOrigin } from 'devframe/client'
@@ -77,12 +77,12 @@ Per the `__devframe/__connection.json` backend:
7777

7878
## Trust & auth (WebSocket mode)
7979

80-
`ensureTrusted()` resolves once the server trusts the client's stored token:
80+
`ensureTrusted()` resolves once the node side trusts the RPC client's stored token:
8181

8282
```ts
8383
const rpc = await connectDevframe()
8484

85-
// Blocks until the server trusts this client (default timeout 60s)
85+
// Blocks until the node side trusts this RPC client (default timeout 60s)
8686
const trusted = await rpc.ensureTrusted()
8787

8888
if (!trusted) {
@@ -100,7 +100,7 @@ The dev server prints a single-use 6-digit code (expires in five minutes, rotate
100100
const ok = await rpc.requestTrustWithCode('047204')
101101
```
102102

103-
A host can embed the code in a link (`buildOtpAuthUrl(origin)`); `connectDevframe` reads the `devframe_otp` fragment, exchanges it, and strips the URL. Rename it with `otpParam`, or set `otpParam: false` to drive it yourself via `authenticateWithUrlOtp(rpc)` / `consumeOtpFromUrl()`.
103+
A host framework can embed the code in a link (`buildOtpAuthUrl(origin)`); `connectDevframe` reads the `devframe_otp` fragment, exchanges it, and strips the URL. Rename it with `otpParam`, or set `otpParam: false` to drive it yourself via `authenticateWithUrlOtp(rpc)` / `consumeOtpFromUrl()`.
104104

105105
### Re-using an existing token
106106

@@ -112,7 +112,7 @@ const ok = await rpc.requestTrustWithToken('a1b2c3…')
112112

113113
### Broadcast-channel sync
114114

115-
`connectDevframe` listens on a shared `BroadcastChannel` (`devframe-auth`) for `auth-update` messages; one tab authenticating trusts every open client.
115+
`connectDevframe` listens on a shared `BroadcastChannel` (`devframe-auth`) for `auth-update` messages; one tab authenticating trusts every open RPC client.
116116

117117

118118
## Calling functions
@@ -132,11 +132,11 @@ const maybe = await my.rpc.callOptional('get-modules', { limit: 10 })
132132
my.rpc.callEvent('notify', { message: 'hello' })
133133
```
134134

135-
Types flow from the server's `defineRpcFunction` definitions.
135+
Types flow from the node side's `defineRpcFunction` definitions.
136136

137137
## Registering client functions
138138

139-
Register functions the server calls via `rpc.broadcast`:
139+
Register functions the node side calls via `rpc.broadcast`:
140140

141141
```ts
142142
import { defineRpcFunction } from 'devframe'
@@ -172,18 +172,18 @@ See [Shared State](/guide/shared-state).
172172

173173
## Services
174174

175-
`rpc.services` mirrors the server's wire-service advertisements:
175+
`rpc.services` mirrors the node side's wire-service advertisements:
176176

177177
```ts
178178
if (rpc.services.has('@devframes/service-open'))
179179
await rpc.services.get('@devframes/service-open')!.rpc.call('open-in-editor', { path })
180180
```
181181

182-
See [Cross-Plugin Services](/guide/services#wire-services).
182+
See [Cross-Devframe Services](/guide/services#wire-services).
183183

184184
## Settings
185185

186-
A scoped client exposes a persisted `settings` store, per-user (`global`) or per-workspace (`project`):
186+
A scoped client exposes a persisted `settings` store, per-user (`global`) or per-checkout (`project`):
187187

188188
```ts
189189
await my.settings.project.set('theme', 'dark')
@@ -213,7 +213,7 @@ Devframe writes a JSON descriptor at `<base>/__connection.json`. The socket shar
213213
}
214214
```
215215

216-
The client resolves it against its origin (`http``ws` / `https``wss`). The field also accepts a `number` (port on the page's host), a full `ws://`/`wss://` URL, or `{ port }` / `{ host }` for a cross-origin side-car.
216+
The RPC client resolves it against its origin (`http``ws` / `https``wss`). The field also accepts a `number` (port on the page's host), a full `ws://`/`wss://` URL, or `{ port }` / `{ host }` for a cross-origin side-car server.
217217

218218
For static mode:
219219

@@ -231,7 +231,7 @@ await connectDevframe({
231231

232232
## Remote docks
233233

234-
Supporting hosts (Vite DevTools; see [its remote-client docs](https://devtools.vite.dev/kit/remote-client)) inject a connection descriptor into the iframe URL that `connectDevframe` auto-detects:
234+
Supporting host frameworks (Vite DevTools; see [its remote-client docs](https://devtools.vite.dev/kit/remote-client)) inject a connection descriptor into the iframe URL that `connectDevframe` auto-detects:
235235

236236
```ts
237237
import { connectDevframe } from 'devframe/client'
@@ -261,7 +261,7 @@ Emitted over `rpc.events`:
261261
| `rpc:is-trusted:updated` | Trust granted, denied, or revoked. Carries the new `isTrusted` boolean. |
262262
| `connection:status` | The [connection status](#handling-connection-and-auth-errors) changes. Carries `(status, previous)`. |
263263
| `connection:error` | A connection-level failure — socket error or trust refused. Carries the `Error`. |
264-
| `rpc:error` | An `rpc.call` rejects, from the server or a down connection. Carries `(error, method)`. |
264+
| `rpc:error` | An `rpc.call` rejects, from the node side or a down connection. Carries `(error, method)`. |
265265

266266
```ts
267267
rpc.events.on('rpc:is-trusted:updated', (isTrusted) => {
@@ -295,10 +295,10 @@ A `static` backend has no live socket, so `rpc.status` stays `connected`.
295295
When the socket closes or trust is refused, in-flight and new `rpc.call` promises reject with a `DevframeConnectionError`, its `kind`:
296296

297297
- `'connection'` — the transport is down (`disconnected` / `error`).
298-
- `'auth'` — the client is `unauthorized`.
298+
- `'auth'` — the RPC client is `unauthorized`.
299299
- `'timeout'` — the call outlived `callTimeout`.
300300

301-
Set `callTimeout` to cap an unresponsive server:
301+
Set `callTimeout` to cap an unresponsive node side:
302302

303303
```ts
304304
const rpc = await connectDevframe({ callTimeout: 10_000 })
@@ -343,11 +343,11 @@ async function loadModules() {
343343

344344
### Recovering
345345

346-
The client doesn't reconnect on its own — reload or re-run your connect routine:
346+
The RPC client doesn't reconnect on its own — reload or re-run your connect routine:
347347

348348
```ts
349349
async function reconnect() {
350-
rpc = await connectDevframe() // a new client; re-subscribe your listeners
350+
rpc = await connectDevframe() // a new RPC client; re-subscribe your listeners
351351
render()
352352
}
353353
```

0 commit comments

Comments
 (0)