Routing conventions, validation, middleware composition and the fetch clients are identical across every framework.
This page is about the places where they aren't - gathered here so you can choose a stack without hunting through six pages of info boxes.
Backends
| Hono | H3 | Koa | |
|---|---|---|---|
| Runtimes | Node · Deno · Bun · Workers · edge | Node · Deno · Bun · edge | Node (Deno/Bun via node:http compat) |
| Handler style | return ctx.json() / ctx.text() | return the value directly | mutate ctx.body |
| Raw params | ctx.req.param() | event.context.params | ctx.params |
| Validated params | ctx.validated.params | ctx.validated.params | ctx.validated.params |
| Route-specific types | Variables, Bindings | Context | State, Context |
Global types (api/env.d.ts) | DefaultVariables, DefaultBindings | DefaultContext | DefaultState, DefaultContext |
| Error entry point | app.onError() | app.use(onError(...)) | middleware around await next() |
| Mixed segments | ⚠️ partial | ⚠️ partial | ✅ full |
| Power syntax | ⚠️ matches, params renamed _0abc | ❌ won't match | ✅ full |
Choosing: take Hono for maximum performance and the widest runtime reach; H3 for the same, with a stronger Web-standards focus; Koa for a mature Node ecosystem - and it is the only backend with complete mixed-segment and power-syntax support.
Frontends
| React | SolidJS | Vue | Svelte | MDX | |
|---|---|---|---|---|---|
| Page extension | .tsx | .tsx | .vue | .svelte | .mdx / .md |
| Layout file | layout.tsx | layout.tsx | layout.vue | layout.svelte | layout.mdx |
| Renders children with | <Outlet/> | props.children | <RouterView/> | {@render children()} | props.children |
jsxImportSource | react | solid-js | vue (JSX only) | n/a | preact |
| Data loading export | loader | preload | loader | loader | loader |
| Reading loaded data | useLoaderData (react-router) | createAsync | useLoaderData (_/use) | useLoaderData (_/use) | useLoaderData (_/use) |
Needs <Suspense> | ❌ | ✅ | ❌ | ❌ | ❌ |
_/use module | ❌ | ❌ | ⚠️ useLoaderData only | ✅ | ✅ |
| Streaming SSR | ✅ | ✅ | ✅ | ❌ | ❌ |
| SSG | ❌ | ❌ | ❌ | ❌ | ✅ |
| TanStack Query | ✅ | ✅ | ✅ | ✅ | ❌ |
| TanStack read hook | useQuery(opts) | useQuery(() => opts) | useQuery(opts) | createQuery(() => opts) | – |
| Mixed segments | ⚠️ .ext suffix only | ❌ | ✅ | ✅ | ✅ |
| Power syntax | ❌ | ❌ | ❌ | ❌ | ❌ |
Reading the exceptions
- SolidJS is the only frontend that needs a
<Suspense>boundary in the common case.createAsyncsuspends; the other frameworks' loaders resolve before render.KosmoJSships no boundary for you - scoping it is your call. Why › - Svelte and MDX render to strings only. They implement
renderToStringbut notrenderToStream, and their folders don't accept the streamingrenderMode. - SSG is MDX-only. For other frameworks, use SSR - or put an MDX folder next to your app folder, which is the intended shape.
- MDX has no client runtime, so TanStack Query is unavailable there. Fetch with an MDX
loaderinstead. - Svelte does not use SvelteKit.
KosmoJSuses only Svelte's UI layer, so data loading is theloaderexport, not SvelteKit'sload, and there are no+pagefiles.
Routing Syntax Support
The parameter syntaxes are the same everywhere; only the exotic ones vary.
| Syntax | Example | Everywhere? |
|---|---|---|
Required [id] | users/[id] | ✅ all backends and frontends |
Optional {id} | users/{id} | ✅ all backends and frontends |
Splat {...path} | docs/{...path} | ✅ all backends and frontends |
| Mixed segment | files/[name].[ext] | ⚠️ see tables above |
| Power syntax | book{-:id}-info | ⚠️ Koa only |
Practical rule: keep frontend routes to the three plain syntaxes. Use mixed segments on the API side, where support is complete on Koa and workable on Hono/H3. Reach for power syntax only on a Koa backend.
Mixing Frameworks
Support differences are per source folder, not per project - a folder runs exactly one frontend and at most one backend. So the differences above are choices you make per app, not constraints you carry project-wide:
src/
├── marketing/ MDX + SSG → static, no backend
├── app/ React + Hono → SSR, streaming, TanStack Query
└── admin/ Vue + H3 → CSRA folder also ignores other frameworks' files: a Vue folder skips .tsx, a React folder skips .vue/.svelte. Details ›