You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 36cdc84
Browse filesBrowse the repository at this point in the historyBrowse files
refactor(vite,nuxt,next): split each into /dev-spa and /hub scopes
Each framework adapter package now exposes two clearly-scoped subpaths for
the two distinct jobs a consumer does, with a bare root that throws a tip:
• `.../dev-spa` — build & dev-serve a SINGLE devframe's SPA with the tool
(Vite: devframeVitePlugin/Bridge/Vite; Next: withDevframe +
createDevframeNextHandler + `/dev-spa/client` React client; Nuxt: the
module, `modules: ['@devframes/nuxt/dev-spa']`).
• `.../hub` — mount a whole @devframes/hub (many integrations) inside the
tool, defaulting the UI slot to @devframes/hub-ui's createUi()
(overridable via `ui`, or `ui: false` for headless), with a browser
client helper at `.../hub/client` over createDevframeClientHost.
• the bare root (`.`) throws a helpful error pointing at both subpaths.
Vite and Nuxt already have native hub viewers (@vitejs/devtools-kit,
@nuxt/devtools), so `@devframes/vite/hub` and `@devframes/nuxt/hub` still
work but emit a one-time console.warn recommending those (silence with
`{ quiet: true }`); `@devframes/next/hub` has no native counterpart and
warns nothing. @devframes/hub and @devframes/hub-ui are optional peers of
all three; hub-ui loads lazily so it stays optional.
The four hub examples now consume the new `/hub` exports: the full
hub-vite/hub-next hosts pass `ui: false` and keep their hand-rolled
clients (the point of those references), while the minimal ones use the
default @devframes/hub-ui. Docs and the AGENTS.md convention section are
updated; tsnapi snapshots regenerated for the new subpaths (allowing the
intentional breaking rename — these packages have not shipped yet).
This PR was created with the help of an agent.
Copy file name to clipboardExpand all lines: AGENTS.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,6 +44,16 @@ The `pnpm test` script intentionally runs `build` first so `tsnapi` snapshots co
44
44
- Utility imports use the package-path form `devframe/utils/*`, never relative `../utils/*`.
45
45
- Dependencies go through the pnpm catalogs in `pnpm-workspace.yaml` (`cli`, `inlined`, `testing`, `types`) - add to a catalog and reference as `catalog:<name>`, don't pin versions in `package.json`.
46
46
47
+
### Framework adapter packages: two scopes, one shape
48
+
49
+
The framework adapter packages - `@devframes/vite`, `@devframes/nuxt`, `@devframes/next` - each split their surface into **two clearly-scoped subpaths**, because a consumer is always doing one of two distinct jobs. Keep all three parallel:
50
+
51
+
-**`.../dev-spa`** - **build & dev-serve a single devframe's SPA** with that tool (the "I'm authoring one devframe" scope). Vite: the `devframeVitePlugin` / `devframeViteBridge` / `devframeVite` plugins. Next: `withDevframe` + `createDevframeNextHandler`, with its React client at `.../dev-spa/client`. Nuxt: the Nuxt module (registered as `modules: ['@devframes/nuxt/dev-spa']`).
52
+
-**`.../hub`** - **mount a whole `@devframes/hub` (many integrations) inside that tool** (the "I'm standing up devtools" scope). Wraps `initHub`, defaults the UI slot to `@devframes/hub-ui`'s `createUi()` (overridable via `ui`, or `ui: false` for headless), and ships a browser client helper at `.../hub/client` (a thin, lifecycle-managing wrapper over `@devframes/hub/client`'s `createDevframeClientHost`). `@devframes/hub` and `@devframes/hub-ui` are **optional peers** of these packages; `hub-ui` is loaded lazily (a bundler-ignored dynamic `import()` in the Next hub) so it stays optional and its `import.meta.url` asset lookups resolve at request time.
53
+
-**The bare root (`.`) throws** a helpful error pointing at the two subpaths - never put real code on it.
54
+
-**Vite and Nuxt already have native hub viewers** (`@vitejs/devtools-kit`, `@nuxt/devtools`), so `@devframes/vite/hub` and `@devframes/nuxt/hub` still work but emit a one-time `console.warn` recommending those (silence with `{ quiet: true }`). `@devframes/next/hub` has no native counterpart, so it warns nothing.
55
+
- The **full hub examples** (`examples/hub-vite`, `examples/hub-next`) consume `.../hub` for the server but keep hand-rolling their own client UI against `@devframes/hub/client` with `ui: false` - that hand-rolled client is the whole point of those reference hosts. The **minimal** ones (`examples/hub-*-minimal`) consume `.../hub` with the default `@devframes/hub-ui` and inject its `embedded.js`, needing no client code.
56
+
47
57
### Design system
48
58
49
59
All five built-in plugins - and every example under `examples/` - share one design system, [`@antfu/design`](https://github.com/antfu/design), so they look and feel like one product across frameworks (Git is React/Next, terminals is Svelte, code-server is Vue, inspect is Vue, a11y is Solid, the examples are Preact/Next/vanilla). It's a dev dependency consumed at build time: its UnoCSS preset and shipped styles drive every surface, and its Vue components are the canonical reference every framework matches. There is no shared internal design package - each app wires the preset itself and owns its own component ports.
Copy file name to clipboardExpand all lines: docs/helpers/next.md
+27-8Lines changed: 27 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,18 +9,19 @@ outline: deep
9
9
10
10
`@devframes/next` hosts devframes from a Next.js App Router app. Next runs on webpack/Turbopack rather than Vite, so it hosts through a route handler instead of the [Vite Bridge](./vite-bridge): the package serves each devframe's SPA and its `__connection.json` from a single `fetch` handler your catch-all route delegates to, reusing devframe's own [`serveStaticHandler`](/adapters/dev) for SPA fallback, content types, and path-traversal guarding.
11
11
12
-
It comes in three parts:
12
+
`@devframes/next` splits into two scopes: `@devframes/next/dev-spa` (author one devframe with Next) and [`@devframes/next/hub`](#mounting-a-hub) (mount a whole devframes-hub). The bare `@devframes/next` import throws with a pointer to both.
13
+
14
+
The `dev-spa` scope comes in two parts:
13
15
14
16
1.**`withDevframe()`** — applies the one Next config setting a devframe host needs.
15
17
2.**`createDevframeNextHandler()`** — hosts a single devframe (the common case).
16
-
3.**`createDevframeNextHost()`** — the lower-level primitive for a hub mounting many devframes at once.
17
18
18
-
Plus a React client surface at `@devframes/next/client`.
19
+
Plus a React client surface at `@devframes/next/dev-spa/client`.
`createDevframeNextHandler(definition)` statically serves the devframe's built SPA and starts a side-car RPC/WebSocket server, advertising it at `<base>/__connection.json`. Delegate your catch-all route to its `fetch`:
`@devframes/next/client` connects to the RPC backend and provides the client to your component tree — the React counterpart to `@devframes/nuxt`'s `$rpc` plugin. Children render immediately, so your shell and a connection indicator stay visible while the client connects.
91
+
`@devframes/next/dev-spa/client` connects to the RPC backend and provides the client to your component tree — the React counterpart to `@devframes/nuxt`'s `$rpc` plugin. Children render immediately, so your shell and a connection indicator stay visible while the client connects.
@@ -119,6 +120,24 @@ Both hooks throw outside a `<RpcProvider>`. Theming and layout stay app-owned.
119
120
120
121
Route handlers that call `fetch` pin `export const runtime = 'nodejs'`: the static handler streams built SPA files from disk, and the side-car RPC/WS server is a Node process.
121
122
123
+
## Mounting a hub
124
+
125
+
`@devframes/next/hub` mounts a whole [devframes-hub](/guide/hub) — many integrations under one namespace — from a single catch-all route. `nextDevframeHub()` returns a route handle memoized on `globalThis` (so Next's dev-time route re-evaluation reuses one instance); `createNextDevframeHub()` is the underlying builder. The UI defaults to `@devframes/hub-ui` (loaded through a bundler-ignored dynamic `import()` so its asset lookups resolve at request time); pass `ui` to swap it or `ui: false` for a headless hub you drive with the React client at `@devframes/next/hub/client` (`useDevframeHubClient()`).
Unlike Vite and Nuxt, Next has no native hub viewer, so this scope prints no recommendation. `createDevframeNextHost()` remains available from `@devframes/next/hub` as the lower-level "bring your own `DevframeHost`" seam for `initHub({ context })`.
140
+
122
141
## See also
123
142
124
143
-[Vite Bridge](./vite-bridge) — the equivalent for Vite-based hosts
Copy file name to clipboardExpand all lines: docs/helpers/nuxt.md
+19-5Lines changed: 19 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,9 @@ outline: deep
4
4
5
5
# Nuxt Helper
6
6
7
-
The `@devframes/nuxt` module wires a Nuxt-built SPA as a devframe client, and optionally serves the dev-time RPC bridge alongside `nuxt dev`. It runs inside the Nuxt app that consumes your devframe.
7
+
The `@devframes/nuxt/dev-spa` module wires a Nuxt-built SPA as a devframe client, and optionally serves the dev-time RPC bridge alongside `nuxt dev`. It runs inside the Nuxt app that consumes your devframe.
8
+
9
+
`@devframes/nuxt` splits into two scopes: `@devframes/nuxt/dev-spa` (this page — author one devframe with Nuxt) and [`@devframes/nuxt/hub`](#mounting-a-hub) (mount a whole devframes-hub). The bare `@devframes/nuxt` import throws with a pointer to both.
8
10
9
11
It handles the four things every Nuxt-powered standalone devtool needs:
10
12
@@ -17,7 +19,7 @@ It handles the four things every Nuxt-powered standalone devtool needs:
17
19
18
20
```ts [nuxt.config.ts]
19
21
exportdefaultdefineNuxtConfig({
20
-
modules: ['@devframes/nuxt'],
22
+
modules: ['@devframes/nuxt/dev-spa'],
21
23
})
22
24
```
23
25
@@ -45,7 +47,7 @@ export function usePayload() {
45
47
46
48
```ts [nuxt.config.ts]
47
49
exportdefaultdefineNuxtConfig({
48
-
modules: ['@devframes/nuxt'],
50
+
modules: ['@devframes/nuxt/dev-spa'],
49
51
devframe: {
50
52
baseURL: './', // where the devframe snapshot lives, relative to the page
51
53
skipAppDefaults: false, // opt out of the app.baseURL / vite.base defaults
@@ -64,7 +66,7 @@ Pass your devframe definition to wire `nuxt dev` up to the RPC backend:
@@ -81,7 +83,7 @@ The bridge is **on by default** whenever `devframe` is set. Skip it (back to cli
81
83
82
84
```ts [nuxt.config.ts]
83
85
exportdefaultdefineNuxtConfig({
84
-
modules: [['@devframes/nuxt', {
86
+
modules: [['@devframes/nuxt/dev-spa', {
85
87
devframe,
86
88
devMiddleware: {
87
89
port: 7777,
@@ -128,6 +130,18 @@ At build time the module:
128
130
129
131
At runtime the built SPA fetches `./__connection.json` (resolved against `document.baseURI`) and branches on the `backend` field — `websocket` in dev, `static` from a `createBuild` snapshot.
130
132
133
+
## Mounting a hub
134
+
135
+
`@devframes/nuxt/hub` mounts a whole [devframes-hub](/guide/hub) — many integrations under one namespace — alongside `nuxt dev`, wiring `@devframes/vite`'s hub plugin into Nuxt's Vite dev server and injecting `@devframes/hub-ui`'s floating dock. The UI defaults to `@devframes/hub-ui`; pass `ui` to swap it or `ui: false` for a headless hub you drive with `@devframes/nuxt/hub/client`.
Nuxt DevTools (`@nuxt/devtools`) integrates the same hub protocol natively and is the recommended path for a Nuxt app, so this module prints a one-time recommendation to that effect (silence it with `{ quiet: true }`).
Copy file name to clipboardExpand all lines: docs/helpers/vite-bridge.md
+19-2Lines changed: 19 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,12 +4,14 @@ outline: deep
4
4
5
5
# @devframes/vite
6
6
7
-
Two Vite plugins for mounting a devframe inside an existing Vite dev server — `devframeVitePlugin` (static mount) and `devframeViteBridge` (RPC bridge) — plus `devframeVite`, a convenience wrapper that picks between them. Used by [`@devframes/nuxt`](./nuxt) and available for any Vite-based host (Astro, SolidStart, plain Vite apps).
7
+
`@devframes/vite` splits into two scopes: **`@devframes/vite/dev-spa`** (this page — dev-serve one devframe's SPA with Vite) and [**`@devframes/vite/hub`**](#mounting-a-hub) (mount a whole devframes-hub inside a Vite app). The bare `@devframes/vite` import throws with a pointer to both.
8
+
9
+
The `dev-spa` scope exports two Vite plugins for mounting a single devframe inside an existing Vite dev server — `devframeVitePlugin` (static mount) and `devframeViteBridge` (RPC bridge) — plus `devframeVite`, a convenience wrapper that picks between them. Used by [`@devframes/nuxt`](./nuxt) and available for any Vite-based host (Astro, SolidStart, plain Vite apps).
8
10
9
11
This sits below the [`vite` adapter](/adapters/vite) on the abstraction ladder: the adapter targets the full Vite DevTools dock; these are the lower-level Vite plugins you reach for when you want a devframe to ride along with an existing app's dev server without the DevTools dock.
@@ -50,3 +52,18 @@ To mount the RPC socket onto the Vite server's own port instead of a side-car
50
52
## `devframeVite` — convenience wrapper
51
53
52
54
`devframeVite(def, { bridge, ...bridgeOptions })` forwards to `devframeViteBridge` when `bridge: true`, or `devframeVitePlugin` otherwise — handy when a single call site needs to switch between the two modes. Reach for the two plugins directly when a devframe needs both mounted at once (e.g. a bridge for RPC alongside a static mount serving its own bundled UI, as the built-in `terminals`/`code-server` plugins do).
55
+
56
+
## Mounting a hub
57
+
58
+
`@devframes/vite/hub` mounts a whole [devframes-hub](/guide/hub) — many integrations under one namespace, one merged RPC registry — inside a Vite dev server with one `viteDevframeHub()` plugin. It wraps `initHub`, shares Vite's HTTP server for the WebSocket, defaults the dock UI to `@devframes/hub-ui` (injecting its `embedded.js` bootstrap into the host page), and mounts everything as connect middleware.
Pass `ui` to swap the viewer or `ui: false` for a headless hub you drive with the client helper at `@devframes/vite/hub/client` (`mountDevframeHubClient()`). Vite DevTools (`@vitejs/devtools-kit`) integrates the same hub protocol natively and is the recommended path for a Vite app, so this plugin prints a one-time recommendation to that effect (silence it with `{ quiet: true }`).
0 commit comments