Skip to content

Commit 88b3933

Browse files
authored
docs: restructure nav into Guide/Adapters/Helpers, minimize READMEs (#7)
* docs: restructure nav into Guide/Adapters/Helpers and minimize READMEs - Split docs/guide/adapters.md into per-adapter pages under docs/adapters/ with an overview index, comparison table, and mount-paths reference. - Promote helpers to their own section under docs/helpers/ — move utilities and Nuxt module pages, lift Vite bridge out of adapters, and expand the open-helpers recipe into a standalone reference. - Rebuild .vitepress/config.ts nav/sidebar with the three top-level sections; add a version dropdown that reads from packages/devframe package.json and links to Release Notes + Contributing. - Add a full favicon head set (icon, apple-touch-icon, mask-icon, theme-color) using the sage brand color. - Add a "Built with Devframe" section to the home page covering Vite DevTools, ESLint Config Inspector, node-modules-inspector, and the three local examples. - Minimize root and packages/devframe READMEs to logo + badges + tagline + docs link, pointing readers at https://devfra.me/. * docs: move "Built with Devframe" into introduction, drop architecture diagram - Move the "Built with Devframe" list from the home page to the end of the introduction so it lives alongside related guide content. - Remove the architecture mermaid diagram from the introduction — the subsystems table and adapters-at-a-glance section already cover the same ground.
1 parent a6c0cfe commit 88b3933

19 files changed

Lines changed: 535 additions & 539 deletions

File tree

README.md

Lines changed: 13 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -6,63 +6,21 @@
66

77
<h1 align="center">Devframe</h1>
88

9-
[![npm version][npm-version-src]][npm-version-href]
10-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
11-
[![bundle][bundle-src]][bundle-href]
12-
[![JSDocs][jsdocs-src]][jsdocs-href]
13-
[![License][license-src]][license-href]
14-
15-
Framework-neutral foundation for building generic DevTools. Describe one devframe — its RPC, its data, its SPA, its CLI shape — and deploy the same definition through any of seven adapters.
16-
17-
Documentation: [https://devfra.me/](https://devfra.me/).
18-
19-
## Install
20-
21-
```sh
22-
pnpm add devframe
23-
```
24-
25-
## Hello, Devframe
26-
27-
```ts
28-
import { defineDevframe, defineRpcFunction } from 'devframe'
29-
import { createCli } from 'devframe/adapters/cli'
30-
31-
const devframe = defineDevframe({
32-
id: 'my-devframe',
33-
name: 'My Devframe',
34-
setup(ctx) {
35-
ctx.rpc.register(defineRpcFunction({
36-
name: 'my-devframe:hello',
37-
type: 'static',
38-
jsonSerializable: true,
39-
handler: () => ({ message: 'hello' }),
40-
}))
41-
},
42-
})
43-
44-
await createCli(devframe).parse()
45-
```
46-
47-
## Adapters
48-
49-
| Adapter | Use case |
50-
|---------|----------|
51-
| `cli` | Standalone CLI tool with `dev` / `build` / `mcp` subcommands. |
52-
| `build` | Generates a static, self-contained SPA snapshot. |
53-
| `vite` | Mounts the devframe into Vite DevTools (or any compatible host) via `@vitejs/devtools-kit`. |
54-
| `embedded` | Overlays inside another devframe's UI. |
55-
| `mcp` | Surfaces the devframe's RPC to coding agents over MCP. |
9+
<p align="center">
10+
<a href="https://npmx.dev/package/devframe"><img src="https://img.shields.io/npm/v/devframe?style=flat&colorA=080f12&colorB=517158" alt="npm version" /></a>
11+
<a href="https://npmx.dev/package/devframe"><img src="https://img.shields.io/npm/dm/devframe?style=flat&colorA=080f12&colorB=517158" alt="npm downloads" /></a>
12+
<a href="https://bundlephobia.com/result?p=devframe"><img src="https://img.shields.io/bundlephobia/minzip/devframe?style=flat&colorA=080f12&colorB=517158&label=minzip" alt="bundle" /></a>
13+
<a href="https://www.jsdocs.io/package/devframe"><img src="https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=517158" alt="JSDocs" /></a>
14+
<a href="https://github.com/devframes/devframe/blob/main/LICENSE.md"><img src="https://img.shields.io/github/license/devframes/devframe.svg?style=flat&colorA=080f12&colorB=517158" alt="License" /></a>
15+
</p>
5616

57-
## Repo layout
17+
<p align="center">
18+
Framework-neutral foundation for building generic DevTools.
19+
</p>
5820

59-
| Path | Description |
60-
|------|-------------|
61-
| [`packages/devframe`](./packages/devframe) | The published [`devframe`](https://www.npmjs.com/package/devframe) npm package. |
62-
| [`packages/nuxt`](./packages/nuxt) | The [`@devframes/nuxt`](https://www.npmjs.com/package/@devframes/nuxt) Nuxt module adapter. |
63-
| [`docs`](./docs) | VitePress documentation site, deployed at https://devfra.me/. |
64-
| [`examples`](./examples) | End-to-end demos: [`devframe-counter`](./examples/devframe-counter), [`devframe-files-inspector`](./examples/devframe-files-inspector), and [`devframe-streaming-chat`](./examples/devframe-streaming-chat). |
65-
| [`tests`](./tests) | Public-API snapshot tests via [`tsnapi`](https://github.com/posva/tsnapi). |
21+
<p align="center">
22+
<b>Documentation:</b> <a href="https://devfra.me/">https://devfra.me/</a>
23+
</p>
6624

6725
## Sponsors
6826

@@ -75,16 +33,3 @@ await createCli(devframe).parse()
7533
## License
7634

7735
[MIT](./LICENSE.md) License © [Anthony Fu](https://github.com/antfu)
78-
79-
<!-- Badges -->
80-
81-
[npm-version-src]: https://img.shields.io/npm/v/devframe?style=flat&colorA=080f12&colorB=517158
82-
[npm-version-href]: https://npmx.dev/package/devframe
83-
[npm-downloads-src]: https://img.shields.io/npm/dm/devframe?style=flat&colorA=080f12&colorB=517158
84-
[npm-downloads-href]: https://npmx.dev/package/devframe
85-
[bundle-src]: https://img.shields.io/bundlephobia/minzip/devframe?style=flat&colorA=080f12&colorB=517158&label=minzip
86-
[bundle-href]: https://bundlephobia.com/result?p=devframe
87-
[license-src]: https://img.shields.io/github/license/devframes/devframe.svg?style=flat&colorA=080f12&colorB=517158
88-
[license-href]: https://github.com/devframes/devframe/blob/main/LICENSE.md
89-
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=517158
90-
[jsdocs-href]: https://www.jsdocs.io/package/devframe

docs/.vitepress/config.ts

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import { fileURLToPath } from 'node:url'
33
import { globSync } from 'tinyglobby'
44
import { defineConfig } from 'vitepress'
55
import { withMermaid } from 'vitepress-plugin-mermaid'
6+
import pkg from '../../packages/devframe/package.json' with { type: 'json' }
67

78
const errorsDir = fileURLToPath(new URL('../errors/', import.meta.url))
89

10+
const repo = 'https://github.com/devframes/devframe'
11+
const brandColor = '#517158'
12+
913
function listErrorCodes(prefix: string): string[] {
1014
return globSync(`${prefix}*.md`, { cwd: errorsDir })
1115
.map(f => f.replace(/\.md$/, ''))
@@ -16,26 +20,53 @@ function guideItems(prefix: string): DefaultTheme.NavItemWithLink[] {
1620
return [
1721
{ text: 'Introduction', link: `${prefix}/guide/` },
1822
{ text: 'Devframe Definition', link: `${prefix}/guide/devframe-definition` },
19-
{ text: 'Adapters', link: `${prefix}/guide/adapters` },
2023
{ text: 'RPC', link: `${prefix}/guide/rpc` },
2124
{ text: 'Shared State', link: `${prefix}/guide/shared-state` },
2225
{ text: 'Streaming', link: `${prefix}/guide/streaming` },
2326
{ text: 'When Clauses', link: `${prefix}/guide/when-clauses` },
2427
{ text: 'Structured Diagnostics', link: `${prefix}/guide/diagnostics` },
25-
{ text: 'Utilities', link: `${prefix}/guide/utilities` },
2628
{ text: 'Client', link: `${prefix}/guide/client` },
2729
{ text: 'Standalone CLI', link: `${prefix}/guide/standalone-cli` },
28-
{ text: 'Nuxt Helper', link: `${prefix}/guide/nuxt` },
2930
{ text: 'Agent-Native (experimental)', link: `${prefix}/guide/agent-native` },
3031
]
3132
}
3233

34+
function adaptersItems(prefix: string): DefaultTheme.NavItemWithLink[] {
35+
return [
36+
{ text: 'Overview', link: `${prefix}/adapters/` },
37+
{ text: 'CLI', link: `${prefix}/adapters/cli` },
38+
{ text: 'Dev', link: `${prefix}/adapters/dev` },
39+
{ text: 'Build', link: `${prefix}/adapters/build` },
40+
{ text: 'Vite', link: `${prefix}/adapters/vite` },
41+
{ text: 'Embedded', link: `${prefix}/adapters/embedded` },
42+
{ text: 'MCP', link: `${prefix}/adapters/mcp` },
43+
]
44+
}
45+
46+
function helpersItems(prefix: string): DefaultTheme.NavItemWithLink[] {
47+
return [
48+
{ text: 'Overview', link: `${prefix}/helpers/` },
49+
{ text: 'Utilities', link: `${prefix}/helpers/utilities` },
50+
{ text: 'Vite Bridge', link: `${prefix}/helpers/vite-bridge` },
51+
{ text: 'Nuxt Module', link: `${prefix}/helpers/nuxt` },
52+
{ text: 'Open Helpers', link: `${prefix}/helpers/open-helpers` },
53+
]
54+
}
55+
3356
export function devframeSidebar(prefix = ''): DefaultTheme.SidebarItem[] {
3457
return [
3558
{
3659
text: 'Guide',
3760
items: guideItems(prefix),
3861
},
62+
{
63+
text: 'Adapters',
64+
items: adaptersItems(prefix),
65+
},
66+
{
67+
text: 'Helpers',
68+
items: helpersItems(prefix),
69+
},
3970
{
4071
text: 'Error Reference',
4172
link: `${prefix}/errors/`,
@@ -48,10 +79,19 @@ export function devframeSidebar(prefix = ''): DefaultTheme.SidebarItem[] {
4879
]
4980
}
5081

51-
export function devframeNav(prefix = ''): DefaultTheme.NavItemWithLink[] {
82+
export function devframeNav(prefix = ''): DefaultTheme.NavItem[] {
5283
return [
53-
...guideItems(prefix),
54-
{ text: 'Error Reference', link: `${prefix}/errors/` },
84+
{ text: 'Guide', items: guideItems(prefix) },
85+
{ text: 'Adapters', items: adaptersItems(prefix) },
86+
{ text: 'Helpers', items: helpersItems(prefix) },
87+
{ text: 'Errors', link: `${prefix}/errors/` },
88+
{
89+
text: `v${pkg.version}`,
90+
items: [
91+
{ text: 'Release Notes', link: `${repo}/releases` },
92+
{ text: 'Contributing', link: `${repo}/blob/main/CONTRIBUTING.md` },
93+
],
94+
},
5595
]
5696
}
5797

@@ -60,22 +100,22 @@ export default withMermaid(defineConfig({
60100
description: 'Framework-neutral foundation for building generic DevTools — RPC layer, hosts, and adapters.',
61101
head: [
62102
['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
103+
['link', { rel: 'apple-touch-icon', href: '/logo.svg' }],
104+
['link', { rel: 'mask-icon', href: '/logo.svg', color: brandColor }],
105+
['meta', { name: 'theme-color', content: brandColor }],
63106
],
64107
themeConfig: {
65108
logo: { light: '/logo.svg', dark: '/logo.svg' },
66-
nav: [
67-
{ text: 'Guide', items: guideItems('') },
68-
{ text: 'Error Reference', link: '/errors/' },
69-
],
109+
nav: devframeNav(),
70110
sidebar: devframeSidebar(),
71111
search: {
72112
provider: 'local',
73113
},
74114
socialLinks: [
75-
{ icon: 'github', link: 'https://github.com/devframes/devframe' },
115+
{ icon: 'github', link: repo },
76116
],
77117
editLink: {
78-
pattern: 'https://github.com/devframes/devframe/edit/main/docs/:path',
118+
pattern: `${repo}/edit/main/docs/:path`,
79119
text: 'Suggest changes to this page',
80120
},
81121
footer: {

docs/adapters/build.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# Build
6+
7+
Produces a self-contained static deploy of a devframe:
8+
9+
1. Copies the author's SPA dist (`cli.distDir` or `options.distDir`) into `<outDir>`.
10+
2. Runs `setup(ctx)` with `mode: 'build'`.
11+
3. Collects RPC dumps for every `'static'` function and any `'query'` function with `dump.inputs` / `snapshot: true`.
12+
4. Writes `<outDir>/__connection.json` (`{ backend: 'static' }`) and sharded dump files under `<outDir>/__rpc-dump/` — both at the SPA root so the deployed client discovers them via relative paths from `document.baseURI`.
13+
5. When `def.spa` is set, also writes `<outDir>/spa-loader.json` describing how the SPA hydrates its data.
14+
15+
```ts
16+
import { createBuild } from 'devframe/adapters/build'
17+
import devframe from './devframe'
18+
19+
await createBuild(devframe, {
20+
outDir: 'dist-static',
21+
base: '/',
22+
})
23+
```
24+
25+
| Option | Default | Description |
26+
|--------|---------|-------------|
27+
| `outDir` | `dist-static` | Output directory. Cleared on each build. |
28+
| `base` | `/` | Absolute URL base the output is served from. |
29+
| `distDir` | `def.cli?.distDir` | Override the SPA dist directory. |
30+
31+
The resulting directory hosts on any static web server (`serve`, nginx, GitHub Pages, …). The client auto-detects `static` mode by resolving `./__connection.json` against `document.baseURI` and runs in read-only form.
32+
33+
`createBuild` copies the SPA verbatim, so deploying under a custom URL base just means building the SPA with relative asset paths (`vite.base: './'`) — the client discovers the effective base at runtime.
34+
35+
When `def.spa` is set on the definition, `createBuild` also writes `spa-loader.json` next to `index.html` describing how the deployed SPA sources its data:
36+
37+
- `'none'` — use the baked RPC dump only (read-only static view).
38+
- `'query'` — hydrate from URL search params.
39+
- `'upload'` — accept a drag-and-drop file.
40+
41+
Deployed SPAs that use `setupBrowser` ship their own client entry that registers the handlers.

docs/adapters/cli.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# CLI
6+
7+
The CLI adapter wraps a `DevframeDefinition` in a `cac`-powered command-line interface. From one entry it spins up an `h3` dev server with WebSocket RPC, builds static snapshots, builds SPA bundles, or starts an MCP server.
8+
9+
```ts
10+
import { defineDevframe } from 'devframe'
11+
import { createCli } from 'devframe/adapters/cli'
12+
13+
const devframe = defineDevframe({
14+
id: 'my-devframe',
15+
name: 'My Devframe',
16+
cli: { distDir: './client/dist' },
17+
setup(ctx) { /* register docks, RPC, etc. */ },
18+
})
19+
20+
await createCli(devframe).parse()
21+
```
22+
23+
Running the resulting binary:
24+
25+
```sh
26+
my-devframe # dev server at http://localhost:9999/
27+
my-devframe --port 8080
28+
my-devframe build --out-dir dist-static
29+
my-devframe build --out-dir dist-static --base /devtools/
30+
my-devframe mcp # stdio MCP server (experimental)
31+
```
32+
33+
Standalone CLI serves the SPA at `/` by default. The `/__devtools/` prefix is for *hosted* adapters where devframe mounts alongside an existing app — see [Mount paths](./#mount-paths).
34+
35+
## Options
36+
37+
`createCli(def, options?)` accepts:
38+
39+
| Option | Default | Description |
40+
|--------|---------|-------------|
41+
| `defaultPort` | `9999` (or `def.cli?.port`) | Port used by the dev command when `--port` isn't provided. |
42+
| `configureCli` || `(cli: CAC) => void` — final hook to add commands/flags at the assembly stage, after the definition's `cli.configure` runs. |
43+
| `onReady` || `(info: { origin, port, app }) => void \| Promise<void>` — called once the dev server is listening. Use this to print your own startup banner. |
44+
45+
`createCli` returns a `CliHandle`:
46+
47+
```ts
48+
interface CliHandle {
49+
cli: CAC // raw cac instance — mutate before calling parse()
50+
parse: (argv?: string[]) => Promise<void>
51+
}
52+
```
53+
54+
The `cli` property lets the caller add ad-hoc commands and flags right before `parse()` when a `configureCli` callback is inconvenient.
55+
56+
## Definition-level `cli` fields
57+
58+
```ts
59+
defineDevframe({
60+
id: 'my-devframe',
61+
cli: {
62+
command: 'my-devframe', // binary name; default: the id
63+
distDir: './client/dist', // required for dev/build/spa
64+
port: 7777, // preferred port
65+
portRange: [7777, 9000], // passed through to get-port-please
66+
random: false, // passed through to get-port-please
67+
host: '127.0.0.1', // default host; --host overrides
68+
open: true, // auto-open the browser on dev start
69+
auth: false, // skip the trust handshake (single-user localhost)
70+
configure(cli) { // contribute capability flags/commands
71+
cli.option('--config <file>', 'Custom config file')
72+
.option('--no-files', 'Skip file matching')
73+
},
74+
},
75+
setup(ctx, { flags }) {
76+
// `flags` is the parsed cac flag bag — includes both devframe's
77+
// built-ins (`--port`, `--host`, `--open`) and anything declared in
78+
// `cli.configure` or `configureCli`.
79+
},
80+
})
81+
```
82+
83+
`distDir` is the only required field; everything else has sensible defaults. The `configure` hook runs *before* the `configureCli` option passed to `createCli`, so the final tool author always has the last word on flags.
84+
85+
## Headless logging
86+
87+
Devframe leaves startup output to the application. Wire `onReady` to print your own banner:
88+
89+
```ts
90+
await createCli(devframe, {
91+
onReady({ origin }) {
92+
console.log(`ESLint Config Inspector ready at ${origin}`)
93+
},
94+
}).parse()
95+
```
96+
97+
Structured diagnostics (via `logs-sdk`) continue to surface through their normal reporters.
98+
99+
## Use your own CLI framework
100+
101+
To integrate devframe into an existing commander / yargs program — or to expose a different command structure than `createCli`'s `dev` / `build` / `mcp` triplet — drop down to the peer factories. Same `DevframeDefinition`, different shell:
102+
103+
| Building block | Entry | Purpose |
104+
|----------------|-------|---------|
105+
| [`createDevServer(def, opts?)`](./dev) | `devframe/adapters/dev` | h3 + WebSocket RPC + SPA mount |
106+
| [`createBuild(def, opts?)`](./build) | `devframe/adapters/build` | Static deploy |
107+
| [`createMcpServer(def, opts?)`](./mcp) | `devframe/adapters/mcp` | stdio MCP server |
108+
| `parseCliFlags(schema, raw)` | `devframe/adapters/cli` | Validate a flag bag against a `CliFlagsSchema` |
109+
110+
See the [Standalone CLI guide](/guide/standalone-cli#use-your-own-cli-framework) for a worked commander example.

0 commit comments

Comments
 (0)