┌──────────────────┐ ┌────────────────────────┐ ┌───────────────────────┐ │ Hono / Elysia │ │ Spiceflow │ │ Next.js App Router │ │ HTTP APIs │ │ APIs + React RSC │ │ File-system React app │ └────────┬─────────┘ └────────────┬───────────┘ └───────────┬───────────┘ │ │ │ v v v JSON routes, middleware .get .page .layout .loader app/**/page.tsx server actions, Link force-dynamic, cache, PPR Node, Bun, Cloudflare
Spiceflow instance. You choose the path. You can colocate an API route and a page, mount a sub-app, or generate routes in a loop. There is no app/ directory, no page.tsx / layout.tsx filename contract, and no parallel-route or intercepting-route conventions.123456789export const app = new Spiceflow() .get('/api/hello', () => ({ message: 'Hello' })) .layout('/*', async ({ children }) => ( <html> <body>{children}</body> </html> )) .page('/', async () => <Home />) .page('/posts/:slug', async ({ params }) => <Post slug={params.slug} />)
.use(). That is awkward in App Router, where API routes, pages, and middleware live in separate file conventions.declare module 'spiceflow/react' registers typeof app. Then router.href(), <Link>, useLoaderData(), and createSpiceflowFetch() all infer paths, params, query, and response types. Next.js does not type your route table. A renamed page.tsx does not fail tsc at every stale <Link href>.dynamic, revalidate, fetch cache, unstable_cache, noStore, cookies() opting a tree into dynamic rendering, or "this component is static except when a child is dynamic." You do not pick RSC payload cache vs full route cache vs data cache./dashboard/settings runs the matching loaders, then the matching layouts, then the page. The next GET does the same. Client navigations refetch RSC for the new path. Server actions re-render the current page. There is no hidden static shell that later becomes dynamic.request ──> loaders ──> layouts ──> page ──> HTML or RSC │ └──> every stage runs for this request no static/dynamic split, no segment cache, no PPR puzzle
Request / Response.app/api route handlers from page.tsx. In Spiceflow both are methods on the same app, so the typed client covers HTML and JSON..layout('/app/*', ...) wraps that prefix. You see the tree in the chain instead of inferring it from directories..loader() returns typed data for pages and useLoaderData(). You do not thread fetch through server components and hope the cache dedupes it.throw redirect('/login') is a 307 with Location. response.status = 404 is a 404. App Router often returns 200 HTML for redirects and not-found UI.'use cache', 'use server' boundary puzzles beyond the usual RSC split. "use client" and "use server" still exist. There is no extra cache directive layer.next/font, no ISR, no PPR. If you need those, Next still fits. If you want a React RSC app you can hold in your head, Spiceflow is the simpler model.Request / Response style, then goes further.openapi plugin and the spec is derived from your routes. You do not rewrite handlers with a separate OpenAPI wrapper.Request and Response. There is no c.text(), c.json(), or c.req helper object.yield in a handler streams Server-Sent Events. No extra SSE helper.validator() wrapper that slows TypeScript. .route({ request, query, params }) is the schema.createSpiceflowFetch() shows up in milliseconds, not seconds.SpiceflowRegister. Hono's RPC client types APIs only.Link, and router.href(). Hono has no typed app router for HTML.new Function() compile. Elysia generates the app with eval / new Function(), which causes bugs and makes the codebase hard to contribute to. Spiceflow is plain functions over a route tree.router.href('/posts/:slug', { slug }) is checked against the same app that serves /posts/:slug."use server" functions are POST endpoints that re-render the page. Elysia has no equivalent.| Capability | Spiceflow | Next.js | Hono | Elysia |
| Type-safe HTTP API | Yes | Partial | Yes | Yes |
| OpenAPI from the route table | Yes | No | Extra | Yes |
| MCP tools from routes | Yes | No | No | No |
| React Server Components | Yes | Yes | No | No |
| Server actions that re-render | Yes | Yes | No | No |
Explicit .page() / .layout() | Yes | Files | No | No |
Typed router.href() / Link | Yes | No | No | No |
| Every request re-runs layouts | Yes | No | n/a | n/a |
| No App Router cache model | Yes | No | n/a | n/a |
| Node, Bun, Cloudflare, same code | Yes | Partial | Yes | Partial |