Skip to content

Commit 304410c

Browse files
committed
docs: rework structure and flow around the standard-handler narrative
Reorganize the documentation to follow the define-once/mount-anywhere story: one definition, one standard handler, adapters as conveniences, visual and agentic, then composing a hub and inheriting the ecosystem. - Reframe the landing page and guide introduction around this narrative. - Elevate initDevframe() as 'The Standard Handler' — the boundary every serving path is built on — and position adapters as conveniences over it. - Regroup the guide sidebar/nav into narrative sections (Define your tool, Mount anywhere, Visual & agentic, Compose a hub, Customize the UI). - Fix stale claims: RPC is validated against any Standard Schema validator (not 'birpc + valibot'), and the hosted default base is /__<id>/. Created with the help of an agent.
1 parent 3d473f3 commit 304410c

7 files changed

Lines changed: 175 additions & 90 deletions

File tree

‎docs/.vitepress/config.ts‎

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,44 @@ function listErrorCodes(prefix: string): string[] {
1919
function guideGroups(prefix: string) {
2020
return [
2121
{
22-
text: 'Fundamentals',
22+
text: 'Introduction',
2323
items: [
2424
{ text: 'Introduction', link: `${prefix}/guide/` },
25+
],
26+
},
27+
{
28+
text: 'Define your tool',
29+
items: [
2530
{ text: 'Devframe Definition', link: `${prefix}/guide/devframe-definition` },
2631
{ text: 'RPC', link: `${prefix}/guide/rpc` },
2732
{ text: 'Shared State', link: `${prefix}/guide/shared-state` },
28-
{ text: 'Client Assets', link: `${prefix}/guide/client-assets` },
29-
{ text: 'Structured Diagnostics', link: `${prefix}/guide/diagnostics` },
30-
{ text: 'Agent-Native', link: `${prefix}/guide/agent-native` },
31-
{ text: 'JSON-Render', link: `${prefix}/guide/json-render` },
3233
{ text: 'Streaming', link: `${prefix}/guide/streaming` },
34+
{ text: 'Client Assets', link: `${prefix}/guide/client-assets` },
3335
{ text: 'Scoped Context', link: `${prefix}/guide/scoped-context` },
34-
{ text: 'Standalone CLI', link: `${prefix}/guide/standalone-cli` },
36+
{ text: 'JSON-Render', link: `${prefix}/guide/json-render` },
37+
{ text: 'Structured Diagnostics', link: `${prefix}/guide/diagnostics` },
38+
{ text: 'When Clauses', link: `${prefix}/guide/when-clauses` },
3539
],
3640
},
3741
{
38-
text: 'Client & Security',
42+
text: 'Mount anywhere',
3943
items: [
44+
{ text: 'The Standard Handler', link: `${prefix}/adapters/initiate` },
45+
{ text: 'Adapters', link: `${prefix}/adapters/` },
46+
{ text: 'Standalone CLI', link: `${prefix}/guide/standalone-cli` },
4047
{ text: 'Client', link: `${prefix}/guide/client` },
4148
{ text: 'Transports', link: `${prefix}/guide/transports` },
4249
{ text: 'Security', link: `${prefix}/guide/security` },
4350
],
4451
},
4552
{
46-
text: 'Hub',
53+
text: 'Visual & agentic',
54+
items: [
55+
{ text: 'Agent-Native', link: `${prefix}/guide/agent-native` },
56+
],
57+
},
58+
{
59+
text: 'Compose a hub',
4760
items: [
4861
{ text: 'Hub', link: `${prefix}/guide/hub` },
4962
{ text: 'Client Scripts & Context', link: `${prefix}/guide/client-context` },
@@ -54,28 +67,21 @@ function guideGroups(prefix: string) {
5467
],
5568
},
5669
{
57-
text: 'Customization',
70+
text: 'Customize the UI',
5871
items: [
5972
{ text: 'Build Your Own JSON-Render Frontend', link: `${prefix}/guide/build-your-own-json-render-frontend` },
6073
{ text: 'Build Your Own Hub UI', link: `${prefix}/guide/build-your-own-hub-ui` },
6174
],
6275
},
63-
{
64-
text: 'References',
65-
items: [
66-
{ text: 'When Clauses', link: `${prefix}/guide/when-clauses` },
67-
{ text: 'Examples', link: `${prefix}/examples/` },
68-
],
69-
},
7076
] satisfies { text: string, items: DefaultTheme.NavItemWithLink[] }[]
7177
}
7278

7379
function adaptersItems(prefix: string) {
7480
return [
7581
{ text: 'Overview', link: `${prefix}/adapters/` },
76-
{ text: 'Initiate (middleware)', link: `${prefix}/adapters/initiate` },
77-
{ text: 'Dev', link: `${prefix}/adapters/dev` },
82+
{ text: 'The Standard Handler', link: `${prefix}/adapters/initiate` },
7883
{ text: 'CLI', link: `${prefix}/adapters/cac` },
84+
{ text: 'Dev', link: `${prefix}/adapters/dev` },
7985
{ text: 'Build', link: `${prefix}/adapters/build` },
8086
{ text: 'Vite DevTools', link: `${prefix}/adapters/vite` },
8187
{ text: 'Embedded', link: `${prefix}/adapters/embedded` },

‎docs/adapters/index.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ outline: deep
44

55
# Adapters
66

7-
An adapter takes a `DevframeDefinition` and deploys it into a specific runtime — a standalone CLI, a Vite plugin, a static snapshot, an embedded host, or an MCP server. Each adapter ships at its own entry point (`devframe/adapters/<name>`); the bundler pulls in only the ones you use.
7+
The lowest-level way to serve a devframe is [the standard handler](./initiate): `initDevframe(def, { base })` returns a Web Standard `(request: Request) => Promise<Response>` that mounts on any catch-all route. Every serving path below is built on it.
8+
9+
Adapters package that same foundation into familiar entry points, so you rarely wire the handler by hand. Each adapter takes a `DevframeDefinition` and deploys it into a specific runtime — a standalone CLI, a dev server, a Vite plugin, a static snapshot, an embedded host, or an MCP server. Each ships at its own entry point (`devframe/adapters/<name>`), so the bundler pulls in only the ones you use.
810

911
Every adapter factory has the shape `createXxx(devframeDef, options?)`. Some adapters draw on an optional peer dependency, installed only when you opt into that adapter: `cac` pulls in [`cac`](https://github.com/cacjs/cac), and `mcp` pulls in [`@modelcontextprotocol/server`](https://github.com/modelcontextprotocol/typescript-sdk).
1012

1113
## Comparison
1214

13-
| Adapter | Entry | Factory | Best for |
15+
| Entry point | Module | Factory | Best for |
1416
|---------|-------|---------|----------|
17+
| [Standard Handler](./initiate) | `devframe/initiate` | `initDevframe(def, { base })` | Mounting the raw `Request → Response` handler into any host |
1518
| [`cac`](./cac) | `devframe/adapters/cac` | `createCac(def, options?)` | Standalone tools run via `node ./my-tool.js` |
1619
| [`dev`](./dev) | `devframe/adapters/dev` | `createDevServer(def, options?)` | Run the dev server programmatically — drive it from any CLI framework |
1720
| [`build`](./build) | `devframe/adapters/build` | `createBuild(def, options?)` | Offline reports, CI artifacts, deployable SPA snapshots |

‎docs/adapters/initiate.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Initiate (standard middleware)
1+
# The Standard Handler
22

3-
Serve a devframe from inside any app that can mount a catch-all route: `initDevframe(def, { base })` returns a live instance whose `.handler` — a web-standard `(request: Request) => Promise<Response>` — carries the whole surface (the SPA, `__connection.json` discovery, the WebSocket RPC endpoint, the auth gate, and the optional MCP route) under one mount base.
3+
`initDevframe()` is the boundary the whole project is built on: it turns a `DevframeDefinition` into a live instance whose `.handler` — a Web Standard `(request: Request) => Promise<Response>` — carries the entire surface (the SPA, `__connection.json` discovery, the WebSocket RPC endpoint, the auth gate, and the optional MCP route) under one mount base. Every other serving path — the [adapters](./), the [framework packages](/frameworks/), and the [hub](../guide/hub-initiate) — is assembled from it. Mount it from inside any app that can serve a catch-all route.
44

55
```ts
66
import { initDevframe } from 'devframe/initiate'

‎docs/guide/hub-initiate.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const hub = initHub({
1818
})
1919
```
2020

21-
`base` is required so the mount path is explicit; pass the exported `DEVFRAMES_HUB_BASE` for the conventional `/__devframes/`. The instance echoes the normalized value back as `hub.base`, so route guards and middleware reference it instead of repeating the string. Every mounted devframe runs its `setup()` against the **shared hub context**: one merged RPC registry (frames can call each other's functions), one shared-state store, one WebSocket transport, one Auth. The instance mirrors `initDevframe`'s surface — `base`, `handler`, `nodeMiddleware`, `attach`, `handleUpgrade`, `ready`, `context`, `connectionMeta()`, `close()` — and the same mount snippets apply; see [the initiate adapter](../adapters/initiate#mount-the-handler).
21+
`base` is required so the mount path is explicit; pass the exported `DEVFRAMES_HUB_BASE` for the conventional `/__devframes/`. The instance echoes the normalized value back as `hub.base`, so route guards and middleware reference it instead of repeating the string. Every mounted devframe runs its `setup()` against the **shared hub context**: one merged RPC registry (frames can call each other's functions), one shared-state store, one WebSocket transport, one Auth. The instance mirrors `initDevframe`'s surface — `base`, `handler`, `nodeMiddleware`, `attach`, `handleUpgrade`, `ready`, `context`, `connectionMeta()`, `close()` — and the same mount snippets apply; see [The Standard Handler](../adapters/initiate#mount-the-handler).
2222

2323
## The shared socket
2424

‎docs/guide/hub.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ ctx.commands.register({
5151
})
5252
```
5353

54-
`args` takes positional valibot schemas (a single `v.object(...)` is unwrapped into the tool's input object); omit it for a zero-argument tool. `safety` defaults to `'action'`. `when` clauses evaluate client-side only and are not enforced for agent calls — opt in a `when`-gated command only if running it outside its UI context is safe.
54+
`args` takes positional [Standard Schema](https://standardschema.dev/) schemas (valibot above; a single `v.object(...)` is unwrapped into the tool's input object); omit it for a zero-argument tool. `safety` defaults to `'action'`. `when` clauses evaluate client-side only and are not enforced for agent calls — opt in a `when`-gated command only if running it outside its UI context is safe.
5555

5656
## Cross-iframe dock activation
5757

0 commit comments

Comments
 (0)