Vite
@devframes/vite splits into @devframes/vite/single (dev-serve one devframe's SPA) and @devframes/vite/hub (mount a hub); the bare import throws.
single exports devframeVitePlugin, devframeViteBridge, and devframeVite; also used by @devframes/nuxt.
import { devframeViteBridge, devframeVitePlugin } from '@devframes/vite/single'
import { defineConfig } from 'vite'
import myDevframe from './my-tool'
export default defineConfig({
/** Statically mounts the built SPA at `/__<id>/`, with no RPC server: */
plugins: [devframeVitePlugin(myDevframe)],
// Or bridge the RPC/WS backend into this dev server instead, so the
// user app owns the SPA:
// plugins: [devframeViteBridge(myDevframe)],
})devframeVitePlugin: static mount
Mounts def.clientAssets at options.base (/__<id>/ default) with SPA fallback. clientAssets accepts a local directory or remote assets.
| Option | Default | Description |
|---|---|---|
base | def.basePath ?? '/__<id>/' | Mount path. |
devframeViteBridge: RPC bridge
Devframe spawns a separate RPC + WS server and registers Vite middleware at <base>__connection.json. To share Vite's port, pass its HTTP server to initDevframe / initHub via server.
| Option | Default | Description |
|---|---|---|
base | def.basePath ?? '/__<id>/' | Mount path. |
port | share Vite's HTTP server | Pin a side-car RPC port instead. |
host | def.cli?.host ?? 'localhost' | Bind host for a pinned side-car. |
flags | none | To def.setup(ctx, { flags }). |
auth | gated (interactive OTP) | false to opt out, or a DevframeAuthHandler for a custom scheme. |
mcp | 'auto' | Expose the MCP route at <base>__mcp. 'auto' mounts once agent tools exist; true forces the origin-only route on (trusts same-machine callers); McpRouteOptions can add an authorization identity check. |
allowedOrigins | loopback-only | Widen the WS origin check for a vite --host / container / tunnel origin: extra origins, a WsOriginRegistry, or false to disable (the auth gate stays the trust boundary). |
devframeVite: convenience wrapper
devframeVite(def, { bridge, ...opts }) forwards to devframeViteBridge when bridge: true, else devframeVitePlugin; use them directly when a devframe needs both.
Mounting a hub
@devframes/vite/hub mounts a hub with viteDevframeHub(): wraps initHub, shares Vite's HTTP server, defaults dock UI to @devframes/hub-ui.
import { viteDevframeHub } from '@devframes/vite/hub'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [viteDevframeHub({ devframes: [] })],
})Pass ui to swap the hub UI provider, ui: false for headless (via @devframes/vite/hub/client's mountDevframeHubClient()). Vite DevTools (@vitejs/devtools-kit) supports this natively; recommended once ({ quiet: true } to silence).
build: true also bakes the hub into vite build output: buildHub writes the static hub subtree into <outDir><base> and the UI's embedded.js tag is injected into the built HTML, so the deployed app ships working devtools against a static backend (baked reads, no live server).