Hybrid adapter cookbook (SPA + SSR)
SSOT: react-interop-migration-charter-2026.md, react-interop-implementation-plan-2026.md.
Shared inputs
routes.manifest.ts—export const voxRoutes, optionalnotFoundComponent/errorComponent/globalPendingComponent.vox-client.ts— typedfetchhelpers:GET(+ JSON query values) for@query,POST+ JSON for@mutation/@server(matches Axum).- Component
*.tsx— named exports next to the manifest.
SPA + islands (default)
- Use
VOX_WEB_EMIT_SCAFFOLD=1onvox buildonce to materializeapp/App.tsx,app/main.tsx, and Vite/Tailwind stubs if missing (seeenv-vars.md). - In
App.tsx, importvoxRoutesand wirereact-routercreateBrowserRouter/RouterProvider, or TanStack/React Router in “library” mode — Vox does not emit framework-specific trees. - Islands: keep
@islandoutputs anddata-vox-islandmounts per existing contracts; hydrate from the same Vite bundle.
SSR track (parallel)
- Consume the same manifest in a framework that supports server loaders (e.g. TanStack Start file routes, Remix, custom RSC shell).
- Prefetch loader data on the server using the same
vox-clientcall shapes as the browser (POST bodies must mirror codegen). - Do not rely on removed outputs (
VoxTanStackRouter.tsx, generatedApp.tsx,serverFns.ts/createServerFn).
TanStack Start scaffold today
vox-cli seeds src/routes/* + routeTree.gen.ts when VOX_WEB_TANSTACK_START=1. Compiler output remains manifest + components; bridge the manifest into your router in user code when you outgrow the default / file route stub.
Troubleshooting
- Missing relative imports:
vox buildvalidates./imports fromroutes.manifest.ts(and optionalApp.tsxinout_dir). - Legacy
@component fn(transitional): unset the escape hatch so classic@component fnis a parse error by default; setVOX_ALLOW_LEGACY_COMPONENT_FN=1only while migrating last fixtures. Usevox migrate web --writefor a deterministic keyword patch, thenvox migrate web --checkin CI to ensure no retired-pattern diagnostics remain.
Release / onboarding checklist (short)
-
vox buildproducesroutes.manifest.ts+vox-client.ts(when RPC/routes exist). -
Scaffold or adapter imports manifest from
dist/(or your configured out dir). -
doctorpasses pnpm/node;components.jsonhasrsc: falsewhen using shadcn; globals.css uses@import "tailwindcss"(v4).