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.

@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.

OptionDefaultDescription
basedef.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.

OptionDefaultDescription
basedef.basePath ?? '/__<id>/'Mount path.
portshare Vite's HTTP serverPin a side-car RPC port instead.
hostdef.cli?.host ?? 'localhost'Bind host for a pinned side-car.
flagsnoneTo def.setup(ctx, { flags }).
authgated (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.
allowedOriginsloopback-onlyWiden 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).