From 304410c68c7ce6d2772d8c73427bb9ea6fa952db Mon Sep 17 00:00:00 2001 From: "Anthony Fu (via agent)" Date: Thu, 20 Aug 2026 08:35:55 +0000 Subject: [PATCH] docs: rework structure and flow around the standard-handler narrative MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 /__/. Created with the help of an agent. --- docs/.vitepress/config.ts | 42 ++++++---- docs/adapters/index.md | 7 +- docs/adapters/initiate.md | 4 +- docs/guide/hub-initiate.md | 2 +- docs/guide/hub.md | 2 +- docs/guide/index.md | 165 ++++++++++++++++++++++++++----------- docs/index.md | 43 ++++++---- 7 files changed, 175 insertions(+), 90 deletions(-) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index f7e21814..c4582d9a 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -19,31 +19,44 @@ function listErrorCodes(prefix: string): string[] { function guideGroups(prefix: string) { return [ { - text: 'Fundamentals', + text: 'Introduction', items: [ { text: 'Introduction', link: `${prefix}/guide/` }, + ], + }, + { + text: 'Define your tool', + items: [ { text: 'Devframe Definition', link: `${prefix}/guide/devframe-definition` }, { text: 'RPC', link: `${prefix}/guide/rpc` }, { text: 'Shared State', link: `${prefix}/guide/shared-state` }, - { text: 'Client Assets', link: `${prefix}/guide/client-assets` }, - { text: 'Structured Diagnostics', link: `${prefix}/guide/diagnostics` }, - { text: 'Agent-Native', link: `${prefix}/guide/agent-native` }, - { text: 'JSON-Render', link: `${prefix}/guide/json-render` }, { text: 'Streaming', link: `${prefix}/guide/streaming` }, + { text: 'Client Assets', link: `${prefix}/guide/client-assets` }, { text: 'Scoped Context', link: `${prefix}/guide/scoped-context` }, - { text: 'Standalone CLI', link: `${prefix}/guide/standalone-cli` }, + { text: 'JSON-Render', link: `${prefix}/guide/json-render` }, + { text: 'Structured Diagnostics', link: `${prefix}/guide/diagnostics` }, + { text: 'When Clauses', link: `${prefix}/guide/when-clauses` }, ], }, { - text: 'Client & Security', + text: 'Mount anywhere', items: [ + { text: 'The Standard Handler', link: `${prefix}/adapters/initiate` }, + { text: 'Adapters', link: `${prefix}/adapters/` }, + { text: 'Standalone CLI', link: `${prefix}/guide/standalone-cli` }, { text: 'Client', link: `${prefix}/guide/client` }, { text: 'Transports', link: `${prefix}/guide/transports` }, { text: 'Security', link: `${prefix}/guide/security` }, ], }, { - text: 'Hub', + text: 'Visual & agentic', + items: [ + { text: 'Agent-Native', link: `${prefix}/guide/agent-native` }, + ], + }, + { + text: 'Compose a hub', items: [ { text: 'Hub', link: `${prefix}/guide/hub` }, { text: 'Client Scripts & Context', link: `${prefix}/guide/client-context` }, @@ -54,28 +67,21 @@ function guideGroups(prefix: string) { ], }, { - text: 'Customization', + text: 'Customize the UI', items: [ { text: 'Build Your Own JSON-Render Frontend', link: `${prefix}/guide/build-your-own-json-render-frontend` }, { text: 'Build Your Own Hub UI', link: `${prefix}/guide/build-your-own-hub-ui` }, ], }, - { - text: 'References', - items: [ - { text: 'When Clauses', link: `${prefix}/guide/when-clauses` }, - { text: 'Examples', link: `${prefix}/examples/` }, - ], - }, ] satisfies { text: string, items: DefaultTheme.NavItemWithLink[] }[] } function adaptersItems(prefix: string) { return [ { text: 'Overview', link: `${prefix}/adapters/` }, - { text: 'Initiate (middleware)', link: `${prefix}/adapters/initiate` }, - { text: 'Dev', link: `${prefix}/adapters/dev` }, + { text: 'The Standard Handler', link: `${prefix}/adapters/initiate` }, { text: 'CLI', link: `${prefix}/adapters/cac` }, + { text: 'Dev', link: `${prefix}/adapters/dev` }, { text: 'Build', link: `${prefix}/adapters/build` }, { text: 'Vite DevTools', link: `${prefix}/adapters/vite` }, { text: 'Embedded', link: `${prefix}/adapters/embedded` }, diff --git a/docs/adapters/index.md b/docs/adapters/index.md index d8e217d6..85136632 100644 --- a/docs/adapters/index.md +++ b/docs/adapters/index.md @@ -4,14 +4,17 @@ outline: deep # Adapters -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/`); the bundler pulls in only the ones you use. +The lowest-level way to serve a devframe is [the standard handler](./initiate): `initDevframe(def, { base })` returns a Web Standard `(request: Request) => Promise` that mounts on any catch-all route. Every serving path below is built on it. + +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/`), so the bundler pulls in only the ones you use. 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). ## Comparison -| Adapter | Entry | Factory | Best for | +| Entry point | Module | Factory | Best for | |---------|-------|---------|----------| +| [Standard Handler](./initiate) | `devframe/initiate` | `initDevframe(def, { base })` | Mounting the raw `Request → Response` handler into any host | | [`cac`](./cac) | `devframe/adapters/cac` | `createCac(def, options?)` | Standalone tools run via `node ./my-tool.js` | | [`dev`](./dev) | `devframe/adapters/dev` | `createDevServer(def, options?)` | Run the dev server programmatically — drive it from any CLI framework | | [`build`](./build) | `devframe/adapters/build` | `createBuild(def, options?)` | Offline reports, CI artifacts, deployable SPA snapshots | diff --git a/docs/adapters/initiate.md b/docs/adapters/initiate.md index 5849963d..9d9b383f 100644 --- a/docs/adapters/initiate.md +++ b/docs/adapters/initiate.md @@ -1,6 +1,6 @@ -# Initiate (standard middleware) +# The Standard Handler -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` — 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. +`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` — 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. ```ts import { initDevframe } from 'devframe/initiate' diff --git a/docs/guide/hub-initiate.md b/docs/guide/hub-initiate.md index c1abaec6..95cbd3e2 100644 --- a/docs/guide/hub-initiate.md +++ b/docs/guide/hub-initiate.md @@ -18,7 +18,7 @@ export const hub = initHub({ }) ``` -`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). +`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). ## The shared socket diff --git a/docs/guide/hub.md b/docs/guide/hub.md index 4362d9ca..5b9068c7 100644 --- a/docs/guide/hub.md +++ b/docs/guide/hub.md @@ -51,7 +51,7 @@ ctx.commands.register({ }) ``` -`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. +`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. ## Cross-iframe dock activation diff --git a/docs/guide/index.md b/docs/guide/index.md index 5e23af12..f7c68f0e 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -2,37 +2,112 @@ outline: deep --- -# Devframe +# Introduction -**Devframe is an asset: define your devtool once, serve it anywhere.** You describe a single tool — its RPC surface, its data model, its SPA, its CLI shape — and the same definition deploys through any of the runtime adapters: a standalone CLI, a self-contained static report, an embedded SPA, an MCP server, and more. Devframe is framework- and build-tool-agnostic — it has no Vite dependency and no opinion on what UI framework your SPA uses. +**Devframe is a framework-neutral foundation for building a devtool once, then bringing it to different hosts, standalone surfaces, and agents.** You describe a single tool — its RPC surface, its shared state, its web interface, its diagnostics, and its agent-facing surface — and the same definition mounts almost anywhere. -[Vite DevTools](https://devtools.vite.dev/) is built on top of devframe. If you need an integrated multi-tool host (docks, command palette, terminals, cross-tool toasts), mount your devframe into Vite DevTools via the [`vite` adapter](/adapters/vite) — or build your own host adapter targeting any environment you like. +Think of Devframe as [`unplugin`](https://unplugin.unjs.io/) for devtools. Where `unplugin` gives plugins a common interface across bundlers, Devframe gives devtools a common definition and a standard way to be mounted into different environments. -## Design principles +## The shared boundary -Devframe keeps its surface focused on one tool, so the same definition stays portable across runtimes: +Most devtools — inspectors, asset viewers, build analyzers, terminals, editor integrations — rebuild the same infrastructure: server–client communication, state synchronization, serialization, static asset hosting, and a web interface. Each one also has to decide, again, how to be embedded, standalone, deployable, or integrated into a larger devtools experience. That work is usually coupled to one framework and to how its dev server serves assets, handles requests, and upgrades connections, so similar features get rebuilt separately across the ecosystem. -- **One tool per definition.** A devframe describes a single integration. Deploy it through any adapter; host-level features that only matter when several tools share a UI (palettes, cross-tool toasts, unified terminals) come from whichever host you mount into — Vite DevTools is one example. -- **Headless.** Hook into `onReady`, `cli.configure`, and friends to print your own startup banners and styling — Devframe stays out of the way. -- **App-owned file watching.** Wire your own watcher (chokidar, fs.watch, …) and signal change via `ctx.rpc.sharedState.set(...)` or event-typed RPCs. -- **Context-aware mount paths.** Standalone adapters (`cli`, `build`) serve at `/` by default; hosted adapters (`vite`, `embedded`) serve at `/./`. Override via `DevframeDefinition.basePath`. -- **SPAs own their base at runtime.** Build with relative asset paths (`vite.base: './'`); `connectDevframe` discovers the effective base from the executing script's location. -- **CLI flags compose.** The `cac` instance is exposed to both the devframe (`cli.configure`) and the caller of `createCac`, so capability flags and app flags merge cleanly. +Devframe frees a devtool from those framework-specific boundaries. A capability is defined once and can run on every supported host, so communities can improve one tool together instead of maintaining parallel versions of the same idea. -## What Devframe provides +## One definition, one standard handler -| Subsystem | What it does | -|-----------|--------------| -| **[Devframe Definition](./devframe-definition)** | One `defineDevframe` call describes your tool once; the adapters deploy it anywhere. | -| **[RPC](./rpc)** | Type-safe bidirectional calls built on birpc + valibot. Supports `query`, `static`, `action`, and `event` types. | -| **[Shared State](./shared-state)** | Observable, patch-synced state that survives reconnects and bridges server ↔ browser. | -| **[JSON-Render](./json-render)** | Opt-in data-driven UI — author a view as a serializable spec, render it standalone or in a hub dock with a replaceable frontend. | -| **[Diagnostics](./diagnostics)** | Coded warnings/errors via `nostics` — registered into the host's shared lookup so adapters and consumers share the same surface. | -| **[Streaming](./streaming)** | One-way (RPC streaming) and two-way (uploads) channel primitives for long-running data. | -| **[When Clauses](./when-clauses)** | VS Code-style conditional expressions for docks, commands, and custom UI. | -| **[Utilities](/helpers/utilities)** | Bundled helpers under `devframe/utils/*` — terminal colors, hashing, editor launch, structured-clone serialization, and more. | -| **[Client](./client)** | Browser-side RPC client (`connectDevframe`) with auto-auth and WebSocket / static modes. | -| **[Agent-Native](./agent-native)** | Opt-in exposure of your tool's surface to coding agents over MCP. | +Every devframe starts with [`defineDevframe()`](./devframe-definition). At its core it associates the identity of a tool with the capabilities it provides: + +```ts +import { defineDevframe } from 'devframe' +import { inspectProject } from './rpc' + +export default defineDevframe({ + id: 'my-tool', + name: 'My Tool', + // package metadata and client entry omitted… + setup(ctx) { + ctx.scope('my-tool').rpc.register(inspectProject) + }, +}) +``` + +The definition is independent of its presentation. [`initDevframe()`](/adapters/initiate) turns it into a live instance whose `handler` is a Web Standard `(request: Request) => Promise`: + +```ts +import { initDevframe } from 'devframe/initiate' +import devframe from './devframe' + +const devtools = initDevframe(devframe, { base: '/__my-tool/' }) + +devtools.handler +// (request: Request) => Promise + +devtools.nodeMiddleware +// (req, res, next) => void — for Connect-style servers (Vite, Rsbuild) +``` + +Behind this handler, Devframe serves the tool's web interface, connection metadata, live RPC, authentication, and the optional MCP endpoint under one namespace. The tool is no longer tied to a particular dev-server API; its boundary is the Web Standard `Request` and `Response`. + +Modern frameworks and runtimes already converge on that boundary. Hono and Nitro work with Web Standard requests directly; Next.js and SvelteKit expose route handlers; Vite and Rsbuild accept Connect-style middleware, for which the same instance provides `nodeMiddleware`. The host still decides how the live RPC connection attaches — sharing its HTTP server, receiving its upgrade events, or using a side-car — and that choice is advertised through `__connection.json`, invisible to the client. See [The Standard Handler](/adapters/initiate) for every mount pattern. + +## Adapters as conveniences + +Mounting the handler directly is the lowest-level option. For common entry points, [higher-level adapters](/adapters/) package the same foundation into familiar forms — a standalone CLI, a dedicated dev server, a Vite DevTools plugin, an MCP server, or a static report: + +```ts +import { createPluginFromDevframe } from '@vitejs/devtools-kit/node' +import { createBuild } from 'devframe/adapters/build' +import { createCac } from 'devframe/adapters/cac' +import { createDevServer } from 'devframe/adapters/dev' +import { createMcpServer } from 'devframe/adapters/mcp' +import devframe from './devframe' + +// Pick the entry points your package ships: +export const runCli = () => createCac(devframe).parse() +export const startServer = () => createDevServer(devframe) +export const vitePlugin = createPluginFromDevframe(devframe) +export const startMcp = () => createMcpServer(devframe, { transport: 'stdio' }) +export const buildReport = () => createBuild(devframe, { outDir: 'dist-static' }) +``` + +A single package can ship several of these from one definition. A build inspector could offer a standalone CLI for any project, generate static reports in CI, appear as a dock inside Vite DevTools, and let an agent query the active build — all backed by the same tool. + +## Visual and agentic + +Once a devtool has a structured boundary, its visual panel is no longer the only interface. The same internal state and capabilities can also be consumed programmatically. Visualizations are effective for exploration, overview, and comparison; agents can retrieve focused context, correlate it with the codebase, and carry out multi-step actions. Both read from one source of truth. + +RPC functions stay private by default and explicitly opt into agent exposure. The [MCP adapter](/adapters/mcp) translates those functions, readable resources, and selected shared state into an agent-consumable surface, with descriptions, schemas, and safety metadata. See [Agent-Native](./agent-native). + +## From one devframe to a hub + +A single devframe is one portable tool. A complete devtools experience becomes more interesting when those tools meet and collaborate. [`@devframes/hub`](./hub) is the framework-neutral composition layer, providing shared concepts such as docks, commands, messages, and terminals. Each devframe runs against a shared context, so tools can contribute capabilities and interact with each other. + +The same mounting model scales to the whole collection — [`initHub()`](./hub-initiate) puts many devframes behind one Web Standard handler: + +```ts +import { createUi } from '@devframes/hub-ui' +import { DEVFRAMES_HUB_BASE, initHub } from '@devframes/hub/initiate' +import { createDataInspectorDevframe } from '@devframes/plugin-data-inspector' +import { createTerminalsDevframe } from '@devframes/plugin-terminals' + +const hub = initHub({ + base: DEVFRAMES_HUB_BASE, + devframes: [createDataInspectorDevframe(), createTerminalsDevframe()], + ui: createUi(), +}) + +hub.handler +// the whole devtools collection as Request → Response +``` + +The mounted devframes share one RPC registry, state store, connection, auth gate, and optional aggregate MCP endpoint. The hub itself is headless: [`@devframes/hub-ui`](./build-your-own-hub-ui) provides a reference interface, and a product can bring its own UI without changing the underlying tools. + +## Inheriting the ecosystem + +Portability does not make every devtool generic. Framework-specific layers can offer richer experiences because they understand their framework's conventions and runtime — the universal parts are shared while the final integrations stay specific. + +[Vite DevTools](https://devtools.vite.dev/) is the first flagship host built on this foundation, using `initHub()` for composition and serving alongside its own Vite, Rolldown, Vitest, and Oxc tooling. The [framework packages](/frameworks/) — [`@devframes/vite`](/frameworks/vite), [`@devframes/nuxt`](/frameworks/nuxt), and [`@devframes/next`](/frameworks/next) — provide nicer conventions over the same handler for authoring a single devframe or mounting a whole hub. See [Built with Devframe](/examples/built-with) for tools already using it. ## Install @@ -40,7 +115,7 @@ Devframe keeps its surface focused on one tool, so the same definition stays por pnpm add devframe ``` -`devframe` ships ESM-only and has no Vite dependency. Adapters with optional peers (the MCP adapter needs `@modelcontextprotocol/server`) surface the requirement at import time. +`devframe` ships ESM-only and has no Vite dependency. Adapters with optional peers (for example, the MCP adapter needs `@modelcontextprotocol/server`) surface the requirement at import time. ## Hello, Devframe @@ -72,8 +147,6 @@ const devframe = defineDevframe({ await createCac(devframe).parse() ``` -The same definition can also be deployed through any of the other adapters — for example, mounted into Vite DevTools via the [`vite` adapter](/adapters/vite). - Run it: ```sh @@ -82,30 +155,26 @@ node ./my-devframe.js build # self-contained static deploy in dist-static/ node ./my-devframe.js mcp # stdio MCP server ``` -The CLI adapter serves the SPA at `/` by default. When the same devframe is embedded inside a host (`vite`, `embedded`), the default becomes `/.my-devframe/`. Override either side via `defineDevframe({ basePath })`. +The CLI adapter serves the SPA at `/` by default. When the same devframe is embedded inside a host (`vite`, `embedded`), the default becomes `/__my-devframe/`. Override either side via `defineDevframe({ basePath })`. -## Adapters at a glance - -Devframe deploys the same `DevframeDefinition` through one of these adapters: - -| Adapter | Entry | Target | -|---------|-------|--------| -| `cli` | `createCac(d).parse()` | Standalone CLI with dev / build / mcp subcommands | -| `vite` | `createPluginFromDevframe(d, opts?)` *(from `@vitejs/devtools-kit/node`)* | Mount the devframe into Vite DevTools (or another compatible host) | -| `build` | `createBuild(d, opts?)` | Self-contained static deploy with baked RPC dumps | -| `embedded` | `createEmbedded(d, { ctx })` | Runtime registration into an existing host | -| `mcp` | `createMcpServer(d, opts)` | Model Context Protocol server | - -See [Adapters](/adapters/) for the full reference. - -## Framework- and build-tool-agnostic +## What Devframe provides -Devframe has zero dependencies on Vite or any `@vitejs/*` package — the same definition runs in any Node environment, with any UI framework, against any build tool. Vite DevTools is one host built on top of devframe; mount your definition there with the [`vite` adapter](/adapters/vite), or write adapters for any other host. +| Subsystem | What it does | +|-----------|--------------| +| **[Devframe Definition](./devframe-definition)** | One `defineDevframe` call describes your tool once; the handler and adapters deploy it anywhere. | +| **[RPC](./rpc)** | Type-safe bidirectional calls built on birpc, validated against any Standard Schema validator. Supports `query`, `static`, `action`, and `event` types. | +| **[Shared State](./shared-state)** | Observable, patch-synced state that survives reconnects and bridges server ↔ browser. | +| **[JSON-Render](./json-render)** | Opt-in data-driven UI — author a view as a serializable spec, render it standalone or in a hub dock with a replaceable frontend. | +| **[Diagnostics](./diagnostics)** | Coded warnings/errors via `nostics` — registered into the host's shared lookup so adapters and consumers share the same surface. | +| **[Streaming](./streaming)** | One-way (RPC streaming) and two-way (uploads) channel primitives for long-running data. | +| **[When Clauses](./when-clauses)** | VS Code-style conditional expressions for docks, commands, and custom UI. | +| **[The Standard Handler](/adapters/initiate)** | `initDevframe()` — the Web Standard `Request → Response` boundary every serving path is built on. | +| **[Client](./client)** | Browser-side RPC client (`connectDevframe`) with auto-auth and WebSocket / static modes. | +| **[Agent-Native](./agent-native)** | Opt-in exposure of your tool's surface to coding agents over MCP. | ## What's next - [Devframe Definition](./devframe-definition) — understand `defineDevframe` and the `DevframeNodeContext` -- [Adapters](/adapters/) — pick the right deployment target for your tool -- [RPC](./rpc) — define type-safe server functions your client can call -- [Agent-Native](./agent-native) — expose your devframe to Claude Desktop, Cursor, or any MCP client - +- [The Standard Handler](/adapters/initiate) — mount the handler into any host +- [Adapters](/adapters/) — pick a convenience entry point for your tool +- [Hub](./hub) — compose many devframes behind one handler diff --git a/docs/index.md b/docs/index.md index cf5494f9..2473f68d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,8 +3,8 @@ layout: home hero: name: Devframe - text: Framework-neutral foundation for DevTools - tagline: One devframe definition, adapters to different environments. Managed communication layer, agent-native. + text: Build a devtool once. Mount it anywhere. + tagline: A framework-neutral foundation for devtools. One definition becomes a Web Standard handler you can mount into any host, ship as a CLI or static report, and expose to coding agents. image: src: /logo.svg alt: Devframe @@ -13,29 +13,36 @@ hero: - theme: brand text: Get Started link: /guide/ + - theme: alt + text: Why Devframe + link: /guide/#the-shared-boundary - theme: alt text: View on GitHub link: https://github.com/devframes/devframe features: - - icon: 🧱 - title: One Definition, Many Adapters - details: A single `defineDevframe` call deploys to CLI, static build, SPA, Vite plugin, embedded overlay, kit host, or MCP server. - link: /guide/devframe-definition + - icon: 🧩 + title: One Definition, One Standard Handler + details: '`defineDevframe()` describes a tool once; `initDevframe()` turns it into a `Request → Response` handler you mount into Hono, Nitro, Next.js, SvelteKit, Vite, Rsbuild, Deno, or Bun.' + link: /adapters/initiate - icon: 🔌 - title: Type-safe RPC - details: Bidirectional, schema-validated calls built on birpc + valibot. Query, static, action, and event function types. + title: Adapters as Conveniences + details: The same definition also becomes a standalone CLI, a dev server, a static report, an MCP server, or a Vite DevTools dock — pick the entry points your package ships. + link: /adapters/ + - icon: 🔁 + title: Type-safe RPC & Shared State + details: Bidirectional calls built on birpc, validated against any Standard Schema validator, plus observable patch-synced state that survives reconnects and bridges server and browser. link: /guide/rpc - - icon: 🔄 - title: Shared State - details: Observable, patch-synced state that survives reconnects and bridges server and browser with structured updates. - link: /guide/shared-state - - icon: 🌊 - title: Streaming Channels - details: One-way RPC streams and two-way upload channels for long-running data, progress reporting, and live feeds. - link: /guide/streaming - icon: 🤖 - title: Agent-Native - details: Surface RPC functions, tools, and resources to coding agents over MCP with a single `agent` field on each function. + title: Visual and Agentic + details: Expose the same internal state and capabilities to a web UI and to coding agents over MCP — one source of truth, two interfaces, each playing to its strengths. link: /guide/agent-native + - icon: 🗂️ + title: From One Devframe to a Hub + details: '`@devframes/hub` composes many devframes behind one handler with docks, commands, terminals, and messages — the composition layer flagship hosts like Vite DevTools build on.' + link: /guide/hub + - icon: 🎨 + title: Built-in Plugins, Any Framework + details: Official plugins span Vue, Svelte, Solid, and React — living proof that devframe owns the protocol and leaves the UI framework choice entirely to the author. + link: /plugins/ ---