Skip to content

Commit bcf3005

Browse files
committed
docs: smooth the tutorials' prose and align their style
Polish the server data inspector tutorial for natural flow (fix awkward phrasings and grammar, normalize 'Step N — Title' headers, correct the stale src/devframe.ts references to src/data-inspector.ts) and fix the renamed tutorial's link in the intro. Apply the same voice and closing conventions to the a11y tutorial.
1 parent a8cbd16 commit bcf3005

3 files changed

Lines changed: 41 additions & 40 deletions

File tree

‎docs/content/1.guide/1.tutorial-server-data-inspector.md‎

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
---
22
title: 'Tutorial: Build a Server Data Inspector'
3-
description: 'Build a Devframe to display and query data from the server side, with a dock in a hub, a static build, a standalone server, and a CLI.'
3+
description: 'Build a devtool that displays and queries live server-side data, then ship it as a hub dock, a static build, a standalone server, and a CLI.'
44
---
55

6-
Let's build a real devtool from sketch: a **Data Inspector** that shows the shape of your server's live state and lets you read any value out of it. We'll get it working first, then teach it new tricks one at a time, a dock in a hub, a static build, a standalone server, a CLI.
6+
Let's build a real devtool from scratch: a **Data Inspector** that shows the shape of your server's live state and lets you read any value out of it. We'll get it working first, then teach it new tricks one at a time: a dock in a hub, a static build, a standalone server, and a CLI.
77

8-
## The shape of a devframe app
9-
10-
Two halves talk over a typed connection: a **server** in your Node process that exposes server functions, and a **browser** client that gets the data and renders them nicely and provides interactivity. Devframe is everything in between, the wire, the UI hosting, auth, builds, a CLI.
8+
You'll need [Node 24+](https://nodejs.org/) and a terminal. Every code block is complete, so you can copy them as you go.
119

12-
## Step 1, Define the tool
10+
## The shape of a devframe app
1311

14-
Everything starts with `defineDevframe`: your tool's name, plus a `setup` where you register what it can do.
12+
A devframe app is two halves talking over a typed connection: a **server** in your Node process that exposes functions, and a **browser** client that calls them and renders the results. Devframe is everything in between: the wire, the UI hosting, auth, builds, and a CLI.
1513

16-
> You will need [Node 24+](https://nodejs.org/) for this tutorial.
14+
## Step 1 — Define the tool
1715

18-
Create the project and the definition:
16+
Everything starts with `defineDevframe`: your tool's name, plus a `setup` where you register what it can do. Create the project and the definition:
1917

2018
```sh
2119
mkdir data-inspector && cd data-inspector
@@ -26,7 +24,8 @@ npm install devframe && npm install -D typescript
2624
```ts [src/data-inspector.ts]
2725
import { defineDevframe } from 'devframe'
2826

29-
// An example server-side data, whatever you want to peek at while your app runs, config, a cache, a DB handle.
27+
// Some example server-side data — whatever you want to peek at while your app
28+
// runs: config, a cache, a DB handle.
3029
const serverState = {
3130
config: { name: 'Acme', port: 3000, debug: false },
3231
users: [
@@ -36,7 +35,7 @@ const serverState = {
3635
featureFlags: { newDashboard: true, betaSearch: false },
3736
}
3837

39-
// A simple query function that follows a dot-path like `users.0.name` into the state.
38+
// A tiny query helper that follows a dot-path like `users.0.name` into the state.
4039
function valueAtPath(root: unknown, path: string): unknown {
4140
if (!path)
4241
return root
@@ -85,9 +84,9 @@ export default dataInspectorFrame
8584

8685
`ctx.rpc.register` publishes a function the browser can call: a namespaced `name`, a `type` (`query` is read-only), and a `handler` that takes the call's arguments and returns JSON. That's the whole server. ([RPC](/guide/rpc) has the other types; [Devframe Definition](/guide/devframe-definition) has every field.)
8786

88-
## Step 2, Add a UI
87+
## Step 2 — Add a UI
8988

90-
Now the browser part. We'll use React for this example, but any framework works, the only devframe-specific line is `connectDevframe`, which opens the connection home.
89+
Now the browser half. We'll use React here, but any framework works — the only devframe-specific line is `connectDevframe`, which opens the connection back to the server.
9190

9291
```sh
9392
npm install react react-dom @devframes/vite
@@ -166,11 +165,11 @@ export function App() {
166165
}
167166
```
168167

169-
`client.call(name, ...args)` reaches your handlers. (We cast `.call` to call by name; wire up a typed registry later and every call is checked end to end, see [RPC](/guide/rpc).)
168+
`client.call(name, ...args)` reaches your handlers. (We cast `.call` and call by name here; wire up a typed registry and every call is checked end to end — see [RPC](/guide/rpc).)
170169

171-
## Step 3, Run it as Development
170+
## Step 3 — Run it in development
172171

173-
To try the tool we just built, we can let Vite serve the UI and hand RPC traffic to devframe:
172+
To try what we've built, let Vite serve the UI and hand RPC traffic to devframe:
174173

175174
```ts [vite.client.config.ts]
176175
import { devframeViteBridge } from '@devframes/vite/single'
@@ -195,21 +194,21 @@ export default defineConfig({
195194
npx vite --config vite.client.config.ts
196195
```
197196

198-
Open the printed URL. Three keys with their types show up, and typing `config.port` or `users.0.name` and hitting **Query** prints the value. Button → `call` → your `handler` → back to the page: that's the whole app, working.
197+
Open the printed URL. The three keys and their types show up, and typing `config.port` or `users.0.name` and hitting **Query** prints the value. Button → `call` → your `handler` → back to the page: that's the whole app working.
199198

200199
> [!WARNING]
201-
> `auth: false` trusts anything that can reach the port. We have it off to make the tutorial easier. But we strongly recommend enabling it if you are publishing it as a tool. See [Security](/guide/security).
200+
> `auth: false` trusts anything that can reach the port. It's off here to keep the tutorial simple — turn it on for anything you publish or expose beyond localhost. See [Security](/guide/security).
202201
203-
Everything below reuses this exact `src/devframe.ts` and `client/`. We only change where they run.
202+
From here on we reuse this same `src/data-inspector.ts` and `client/` unchanged; all that changes is where they run.
204203

205-
## Step 4, Dock it in a hub
204+
## Step 4 — Dock it in a hub
206205

207-
A [hub](/guide/hub) puts many devframes behind one interface, each a **dock** you switch between, the tool's own UI in an iframe. Since our client uses a bare `connectDevframe()`, it already works anywhere; the hub just needs the built UI. Point the definition at it:
206+
A [hub](/guide/hub) puts many devframes behind one interface, each a **dock** you switch between — the tool's own UI in an iframe. Since our client uses a bare `connectDevframe()`, it already works anywhere; the hub just needs the built UI, so point the definition at it:
208207

209-
```ts [src/devframe.ts]
208+
```ts [src/data-inspector.ts]
210209
import { fileURLToPath } from 'node:url'
211210
// …
212-
export default defineDevframe({
211+
const dataInspectorFrame = defineDevframe({
213212
id: 'data-inspector',
214213
// …
215214
clientAssets: fileURLToPath(new URL('../dist/client', import.meta.url)),
@@ -244,11 +243,11 @@ export default defineConfig({
244243
npx vite --config vite.hub.config.ts
245244
```
246245

247-
Your inspector now sits in the hub's rail as a dock. Drop more into `devframes: [...]`, your own or the [built-in plugins](/plugins), and each gets its own. (The hub prints a code to authorize on first connect.)
246+
Your inspector now sits in the hub's rail as a dock. Add more to `devframes: [...]` — your own or the [built-in plugins](/plugins) — and each gets its own. (The hub prints a code to authorize on first connect.)
248247

249-
## Step 5, Build a static version
248+
## Step 5 — Build a static version
250249

251-
Some tools should work with no server at all, a report you can drop on any static host. `createBuild` renders the UI and **bakes in** the results of read-only calls. Opt one in with `snapshot: true`:
250+
Some tools should work with no server at all — a report you can drop on any static host. `createBuild` renders the UI and **bakes in** the results of read-only calls. Opt one in with `snapshot: true`:
252251

253252
```ts
254253
ctx.rpc.register({
@@ -274,9 +273,9 @@ npx vite build # refresh dist/client
274273
node scripts/build.mjs # → dist-static/
275274
```
276275

277-
Serve `dist-static/` anywhere and the meta list renders from the baked snapshot, no Node in sight. `query` takes an argument, so it needs the live server (next), or bake specific inputs ([Client Assets](/guide/client-assets)).
276+
Serve `dist-static/` anywhere and the meta list renders from the baked snapshot, no Node in sight. `query` takes an argument, so it still needs the live server (next) — or you can bake specific inputs ([Client Assets](/guide/client-assets)).
278277

279-
## Step 6, Run it standalone
278+
## Step 6 — Run it standalone
280279

281280
The definition never depended on Vite. `createDevServer` runs the tool on its own, serving the UI from `clientAssets` and answering RPC live:
282281

@@ -292,11 +291,11 @@ npx vite build
292291
node scripts/serve.mjs
293292
```
294293

295-
Same UI, same live calls, no bundler in the loop. This is what you'd drop into your own Node program.
294+
Same UI, same live calls, no bundler in the loop — this is what you'd drop into your own Node program.
296295

297-
## Step 7, Give it a CLI
296+
## Step 7 — Give it a CLI
298297

299-
Finally, if you want to provide a CLI for standalone use, which wraps that server in a command shell. `devframe/adapters/cac` made it easy to automatically turn a devframe into a CLI with `dev`, `build`, and `mcp` commands. For example:
298+
Finally, wrap that server in a command shell. `devframe/adapters/cac` turns a devframe into a CLI with `dev`, `build`, and `mcp` commands:
300299

301300
```js [bin.mjs]
302301
#!/usr/bin/env node
@@ -314,13 +313,13 @@ node bin.mjs build # the static build from Step 5
314313
node bin.mjs mcp # expose the tool to a coding agent over MCP
315314
```
316315

317-
While you can also build a CLI on your own with the functions provides above.
316+
You can also assemble your own CLI from the adapter functions used above.
318317

319-
Let's all for this tutorial. If you want to see a full-featured server data inspector, we have it a as a ready-to-use [plugin](/plugins/data-inspector) that you can play with or reference to.
318+
That's it for this tutorial. For a full-featured version, there's a ready-to-use [Data Inspector plugin](/plugins/data-inspector) to use or read for reference.
320319

321320
## What's next
322321

323-
- [RPC](/guide/rpc), `action` and `event` calls, end-to-end types, schema validation
324-
- [Shared State](/guide/shared-state), push live changes to the UI without polling
325-
- [Hub](/guide/hub), docks, commands, terminals across many tools
326-
- [Agent-Native](/guide/agent-native), expose your tool to coding agents over MCP
322+
- [RPC](/guide/rpc) — `action` and `event` calls, end-to-end types, schema validation
323+
- [Shared State](/guide/shared-state) — push live changes to the UI without polling
324+
- [Hub](/guide/hub) — docks, commands, terminals across many tools
325+
- [Agent-Native](/guide/agent-native) — expose your tool to coding agents over MCP

‎docs/content/1.guide/2.tutorial-a11y.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Some devtools need to reach *into* the page you're inspecting — highlight an e
77

88
The point isn't the a11y check — it's the wiring. You'll see the two halves of a devtool talk to each other, and how a plugin pushes notifications up to the host.
99

10-
You'll need **Node 20+** and a terminal. Every code block is complete.
10+
You'll need [Node 20+](https://nodejs.org/) and a terminal. Every code block is complete, so you can copy them as you go.
1111

1212
## The two halves, and why they can't just call each other
1313

@@ -310,8 +310,10 @@ We duck-typed `messages` in the agent rather than importing a hub type, so the a
310310
- **A same-origin channel** — the panel (iframe) and agent (host page) coordinating over `BroadcastChannel`, no server involved, each doing only what its realm allows.
311311
- **The messages feed** — the agent pushing notifications up to the hub with `ctx.messages`.
312312

313+
That's it for this tutorial. For a full-featured version — axe-core, per-route tracking, and message→dock navigation — there's a ready-to-use [Accessibility Inspector plugin](/plugins/a11y) to use or read for reference.
314+
313315
## What's next
314316

315317
- [Client Scripts & Client Context](/guide/client-context) — the full `DockClientScriptContext`: docks, commands, renderers, `when`
316318
- [Hub](/guide/hub) — the messages, docks, commands, and terminals subsystems
317-
- [Accessibility Inspector](/plugins/a11y) — the real plugin this tutorial distills, with axe-core, route tracking, and message→dock navigation
319+
- [Agent-Native](/guide/agent-native) — expose your tool to coding agents over MCP

‎docs/content/1.guide/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ The CLI adapter serves the SPA at `/`; embedded in a host (`vite`, `embedded`) t
169169

170170
## What's next
171171

172-
- [Tutorial: Build a Data Inspector](/guide/tutorial) — go from an empty folder to a shippable devtool, one capability at a time
172+
- [Tutorial: Build a Server Data Inspector](/guide/tutorial-server-data-inspector) — go from an empty folder to a shippable devtool, one capability at a time
173173
- [Tutorial: An Inspector That Talks to the Page](/guide/tutorial-a11y) — client scripts, host↔panel communication, and the messages feed
174174
- [Devframe Definition](/guide/devframe-definition) — `defineDevframe` and `DevframeNodeContext`
175175
- [The Standard Handler](/adapters/initiate) — mount into any host

0 commit comments

Comments
 (0)