Skip to content

feat(vite,nuxt,next): dev-spa vs hub scoped subpaths + extract @devframes/vite - #202

Merged
antfu merged 7 commits into
mainfrom
feat/extract-vite-bridge-package
Aug 14, 2026
Merged

feat(vite,nuxt,next): dev-spa vs hub scoped subpaths + extract @devframes/vite#202
antfu merged 7 commits into
mainfrom
feat/extract-vite-bridge-package

Conversation

@antfubot

@antfubot antfubot commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two related changes to the framework adapter packages:

  1. Extract @devframes/vite from devframe/helpers/vite into its own package, so it can depend on vite directly (typed against Vite's real Plugin/ViteDevServer) while devframe core stays vite-free.
  2. Split @devframes/vite, @devframes/nuxt, and @devframes/next into two clearly-scoped subpaths, because a consumer is always doing one of two distinct jobs. The bare root now throws a helpful tip.

The two scopes (parallel across all three packages)

  • .../dev-spa — build & dev-serve a single devframe's SPA with that tool.
    • Vite: devframeVitePlugin / devframeViteBridge / devframeVite.
    • Next: withDevframe + createDevframeNextHandler, React client at .../dev-spa/client.
    • Nuxt: the Nuxt module — modules: ['@devframes/nuxt/dev-spa'].
  • .../hub — mount a whole @devframes/hub (many integrations) inside that tool. 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 lifecycle-managing wrapper over createDevframeClientHost — a vanilla fn for Vite, a useDevframeHubClient() hook for Next/React, a Vue composable for Nuxt).
  • The bare root (.) throws an error pointing at the two subpaths.

Vite/Nuxt hub notice

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.

Dependencies

@devframes/hub and @devframes/hub-ui are optional peers of all three packages (the /dev-spa scope needs neither); 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.

Examples

The four hub examples now consume the new /hub exports. The full hub-vite/hub-next hosts pass ui: false and keep hand-rolling their own client UI against @devframes/hub/client (the whole point of those reference hosts); the minimal ones use the default @devframes/hub-ui and inject its embedded.js. Also fixed a latent bug where terminals/code-server's bridge plugin silently dropped port/host/flags overrides.

Meta

Docs (helpers/vite-bridge.md, helpers/nuxt.md, helpers/next.md, adapters/*, guide/*, errors/*) and a new AGENTS.md convention section document the two-scope shape. tsnapi API snapshots regenerated for the new subpaths (allowing the intentional breaking rename — these packages have not shipped yet).

Verification

pnpm lint && pnpm knip && pnpm test && pnpm typecheck && pnpm build all pass across the whole repo (1127 tests; 23 build tasks incl. hub-vite/hub-next; 28 typecheck tasks).


This PR was created with the help of an agent.

Move packages/devframe/src/helpers/vite.ts into its own package,
@devframes/vite, mirroring the existing @devframes/next/@devframes/nuxt
integration-package pattern. Being a separate package, it can now depend
on vite directly — viteDevBridge's return type and configureServer hook
are typed against vite's real Plugin/ViteDevServer surface instead of a
hand-rolled duck-typed interface, while devframe core stays free of any
vite dependency.

- devframe/internal gains diagnostics/resolveBasePath/normalizeBasePath
  re-exports so the new package reuses core's DF0033 diagnostic and
  mount-base logic instead of duplicating it.
- The 8 built-in plugins with a vite.ts (inspect, messages, terminals,
  code-server, og, assets, data-inspector, a11y) and @devframes/nuxt now
  import viteDevBridge from @devframes/vite.
- Updates turbo.json's build graph, alias.ts/tsconfig.base.json,
  vitest.config.ts projects, knip.jsonc, docs, and the tsnapi API
  snapshots accordingly.

This PR was created with the help of an agent.
@netlify

netlify Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit 27b454b
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a7e8f8d716ef50008b3a429
😎 Deploy Preview https://deploy-preview-202--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

viteDevBridge conflated two different Vite plugins behind one
devMiddleware option. Split it into two purpose-named exports plus a
convenience wrapper, all served as real Vite Plugin objects:

- devframeVitePlugin(def, { base? }) — statically mounts the built
  SPA, no RPC server.
- devframeViteBridge(def, { base?, port?, host?, flags?, auth?, mcp? })
  — the RPC/WS bridge, options flattened (no more nested
  devMiddleware: boolean | {...}).
- devframeVite(def, { bridge?, ...bridgeOptions }) — dispatches to
  one of the two above, the direct (renamed) successor to the old
  combined function.

Updates every consumer: the 6 single-purpose plugin wrappers (inspect,
messages, og, assets, data-inspector, a11y) switch to devframeVite;
terminals/code-server (which always run both plugins together) call
devframeViteBridge + devframeVitePlugin explicitly — this also fixes a
latent bug where their bridge plugin silently dropped any
port/host/flags override. @devframes/nuxt's always-bridge call site
uses devframeViteBridge directly. Refreshes docs, JSDoc cross-references,
and tsnapi API snapshots (allowing the intentional breaking rename —
this package has not shipped yet).

This PR was created with the help of an agent.
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.
@antfubot antfubot changed the title feat: extract viteDevBridge into a standalone @devframes/vite package feat(vite,nuxt,next): dev-spa vs hub scoped subpaths + extract @devframes/vite Aug 14, 2026
Document the 0.9 framework-adapter changes in the migration guide: the
Vite bridge moving from `devframe/helpers/vite` to `@devframes/vite`
(with `viteDevBridge` → `devframeVite`/`devframeVitePlugin`/
`devframeViteBridge` and the flattened bridge options), the
`@devframes/nuxt` and `@devframes/next` `/dev-spa` split (and the
throwing bare root), and the new `/hub` scope for mounting a hub inside
a tool.

This PR was created with the help of an agent.
…dge-package

# Conflicts:
#	examples/hub-next-minimal/src/client/hub.ts
#	examples/hub-vite-minimal/vite.config.ts
… Guide

The three `@devframes/*` framework packages no longer sit under "Helpers"
(they're first-class packages, not `devframe/*` helpers) — they move into a
new top-level **Frameworks** section (`docs/frameworks/`) with a cross-
framework overview plus one page each for Vite / Nuxt / Next, organized
around the two scopes (`/dev-spa` authoring one devframe, `/hub` mounting a
hub). "Helpers" keeps just the genuine helpers (utilities + recipes).

Also breaks the flat 21-item Guide sidebar into labelled subsections
(Fundamentals / Client & Security / JSON-Render / Hub / Recipes & Advanced)
— the top-nav dropdown still renders the flattened list. Renames the
Adapters "Vite" entry to "Vite DevTools" to disambiguate the external
`@vitejs/devtools-kit` adapter from `@devframes/vite`, and updates every
cross-link to the moved pages.

This PR was created with the help of an agent.
…dge-package

# Conflicts:
#	examples/hub-vite-minimal/vite.config.ts
#	examples/hub-vite/src/vite-devframe-hub.ts
@antfu
antfu merged commit 3bfcd2a into main Aug 14, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants