Comparison
This table compares @lazarv/react-server against other popular React frameworks and routing solutions. The comparison covers full-stack features, architecture, routing, type safety, search params, scroll restoration, and developer experience.
This comparison summarizes the feature set described in the documentation. It focuses on first-class, built-in support rather than custom userland solutions. Some rows describe core architecture, others cover convenience or router ergonomics, so the table should be read as a map of tradeoffs, not a single score.
This comparison is maintained by the
@lazarv/react-serverteam. If you find an inaccuracy, please open an issue — we want this to be fair and factual.
Legend:
- ✅ — First-class, built-in support that is documented and part of the framework’s intended model
- 🟡 — Partial support, important limitations, or support that exists only in a narrower subset of use cases
- 🔶 — Possible through userland composition, community plugins, or manual setup, but not a first-class built-in feature
- 🛑 — No meaningful built-in support
| @lazarv/react-server | Next.js | TanStack Start | React Router | Waku | |
|---|---|---|---|---|---|
| React Server Components | ✅ | ✅ | 🟡 | 🟡 | ✅ |
| Server Functions (actions) | ✅ | ✅ | ✅ | 🟡 | ✅ |
| Server Function Defense Layer | ✅ encrypted refs + hardened decoder | 🟡 IDs/origin/body cap | 🟡 CSRF + validators | 🔶 route action model | 🔶 auth/userland |
| SSR | ✅ | ✅ | ✅ | ✅ | ✅ |
| Streaming SSR | ✅ | ✅ | ✅ | ✅ | ✅ |
| API Routes | ✅ | ✅ | ✅ | ✅ | ✅ |
| API / Route Middleware | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Server Function Middleware | 🔶 not first-class | 🛑 | ✅ client/server chain | 🔶 not first-class | 🛑 |
| Static Site Generation | ✅ | ✅ | 🟡 | 🟡 | ✅ |
| Partial Pre-rendering (PPR) | ✅ | ✅ | 🛑 | 🛑 | 🛑 |
| Response Caching (TTL) | ✅ | ✅ | 🛑 | 🛑 | 🛑 |
| Redirects (server) | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Rewrites (server) | ✅ | ✅ | 🛑 | 🛑 | 🛑 |
| Reload / Invalidation | ✅ | ✅ | ✅ | ✅ | 🛑 |
| @lazarv/react-server | Next.js | TanStack Start | React Router | Waku | |
|---|---|---|---|---|---|
| Open Runtime (no vendor lock-in) | ✅ | 🟡 optimized for Vercel | ✅ | ✅ | ✅ |
| Vite-based | ✅ | 🛑 | ✅ | ✅ | ✅ |
| Production HTTP Layer | ✅ backpressure + security | 🟡 platform-managed | 🔶 host/adapter | 🔶 host/adapter | 🔶 host/adapter |
| Observability | ✅ OTel traces + metrics | ✅ OTel spans | 🟡 manual/experimental | 🟡 instrumentation API | 🔶 userland |
| Hydration Islands | ✅ | 🛑 | 🟡 deferred tree only | 🛑 | 🛑 |
| Multiple Deploy Targets | ✅ | 🟡 | ✅ | ✅ | ✅ |
| Micro-frontend / Remote Components | ✅ | 🔶 | 🛑 | 🛑 | 🛑 |
| MCP Server Integration | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Worker / Multi-threaded Rendering | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Cluster Mode | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Adapter-based Deployment | ✅ | 🟡 | ✅ | ✅ | ✅ |
| @lazarv/react-server | Next.js | TanStack Router | React Router | Waku | |
|---|---|---|---|---|---|
| Nested / Layout Routes | ✅ | ✅ | ✅ | ✅ | ✅ |
| Code-based Routes | ✅ | 🛑 | ✅ | ✅ | 🛑 |
| File-based Routes | ✅ | ✅ | ✅ | ✅ | ✅ |
| Virtual / Programmatic Routes | ✅ | 🛑 | ✅ | ✅ | 🛑 |
| Ranked Route Matching | ✅ | ✅ | ✅ | ✅ | 🛑 |
| Suspense Route Transitions | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Suspense Route Elements | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Error Boundary Elements | ✅ | ✅ | ✅ | ✅ | ✅ |
| Loading / Pending Elements | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Client-only Routes | ✅ | 🛑 | ✅ | ✅ | 🛑 |
| Parallel Routes / Outlets | ✅ | ✅ | 🛑 | 🛑 | 🟡 |
| Route Prefetching | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Automatic Prefetching | ✅ | ✅ | ✅ | ✅ | 🛑 |
| Active Link Customization | ✅ | ✅ | ✅ | ✅ | 🛑 |
| Navigation Guards / Blocker | ✅ | 🛑 | ✅ | 🟡 | 🛑 |
<Form> Component | ✅ | ✅ | 🛑 | ✅ | 🛑 |
| Deferred / Streaming Primitives | ✅ | ✅ | ✅ | ✅ | 🟡 |
| @lazarv/react-server | Next.js | TanStack Router | React Router | Waku | |
|---|---|---|---|---|---|
| Typesafe Route Paths | ✅ | 🟡 | ✅ | 🟡 | 🛑 |
| Typesafe Path Params | ✅ | 🛑 | ✅ | ✅ | 🟡 |
| Typesafe Navigation | ✅ | 🟡 | ✅ | 🟡 | 🛑 |
| Typesafe Search Params | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Path Param Validation | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Path Param Coercion / Parsing | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Typed Link Components | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Typed Hooks (useParams, useSearchParams) | ✅ | 🛑 | ✅ | 🟡 | 🛑 |
| Auto-generated Route Types (file-router) | ✅ | 🟡 | ✅ | 🛑 | 🛑 |
| Branded Outlet Types | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Multi-library Schema Support (Zod, ArkType, Valibot) | ✅ | 🛑 | 🟡 | 🛑 | 🛑 |
| Lightweight Parse Functions (no schema library) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| @lazarv/react-server | Next.js | TanStack Router | React Router | Waku | |
|---|---|---|---|---|---|
| Basic Search Params | ✅ | ✅ | ✅ | ✅ | 🟡 |
| Search Param Hooks | ✅ | ✅ | ✅ | ✅ | 🛑 |
| Typed Search Params | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Search Param Schema Validation | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
<Link> / useNavigate Search API (object, not string) | ✅ | 🟡 | ✅ | 🟡 | 🛑 |
Functional Search Updaters (prev => next) | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Search Param Transforms (encode/decode boundary) | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Route-scoped Search Transforms | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Custom Search Parsing/Serialization | ✅ | 🛑 | ✅ | 🔶 | 🛑 |
| @lazarv/react-server | Next.js | TanStack Router | React Router | Waku | |
|---|---|---|---|---|---|
| Window Scroll Restoration | ✅ | 🟡 | ✅ | ✅ | 🟡 |
| Element / Container Scroll Restoration | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Async Content Scroll Restoration | ✅ | 🛑 | ✅ | 🛑 | 🛑 |
| Per-route Scroll Customization | ✅ | 🛑 | 🟡 | 🛑 | 🛑 |
| Zero-flash Restoration (pre-hydration script) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
prefers-reduced-motion Aware | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Hash / Anchor Scrolling | ✅ | ✅ | ✅ | ✅ | 🛑 |
| Config-level Enable (zero code) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Query-only Changes Preserve Scroll | ✅ | 🛑 | 🟡 | 🛑 | 🛑 |
| @lazarv/react-server | Next.js | TanStack Router | React Router | Waku | |
|---|---|---|---|---|---|
| Typed Resource Descriptors | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Schema-validated Resource Keys | ✅ | 🛑 | 🟡 | 🛑 | 🛑 |
Suspense-integrated .use() Hook | ✅ | 🛑 | ✅ | 🟡 | 🛑 |
| Resource Invalidation (per-key) | ✅ | 🟡 | ✅ | 🛑 | 🛑 |
| Resource Collections | ✅ | 🛑 | 🛑 | 🛑 | 🛑 |
| Route-Resource Binding (prefetch) | ✅ | 🛑 | ✅ | ✅ | 🛑 |
| Router Loaders (data fetching) | ✅ RSC + resources | 🟡 | ✅ | ✅ | 🟡 |
| SWR / Stale-While-Revalidate Caching | ✅ "use cache" | ✅ | ✅ | 🛑 | 🛑 |
| Server & Client Loaders | ✅ | 🟡 | ✅ | ✅ | 🛑 |
| @lazarv/react-server | Next.js | TanStack Router | React Router | Waku | |
|---|---|---|---|---|---|
| Zero-config File Router | ✅ | ✅ | 🟡 | 🟡 | ✅ |
| MDX Pages | ✅ | 🔶 | 🛑 | 🛑 | 🛑 |
| Virtual Routes Module | ✅ | 🛑 | 🟡 | 🟡 | 🛑 |
| Route-scoped Loading / Error / Fallback Files | ✅ | ✅ | 🛑 | 🛑 | 🛑 |
| Devtools | ✅ | 🛑 | ✅ router only | 🟡 | 🛑 |
| Route Masking | 🔶 URL identity model | 🛑 | ✅ | 🛑 | 🛑 |
| Route-level Typed Dependencies | ✅ Typesafe resources | 🛑 | ✅ Typesafe route context + loaders | 🛑 | 🛑 |
| Route Lifecycle Hooks | 🔶 guards + React lifecycle | 🛑 | ✅ | 🛑 | 🛑 |
@lazarv/react-server is a full React Server Components runtime — not just a router. The routing system is deeply integrated with RSC streaming, server functions, and the Vite build pipeline. This means features like typed routes, client-only routes, and server-side validation work end-to-end without glue code.
Unlike routers that bolt RSC support on top, @lazarv/react-server was built from the ground up for React Server Components. Every route can mix server and client components freely.
@lazarv/react-server ships a production runtime with keep-alive and timeout tuning, admission control, adaptive ELU-based backpressure, request/body and multipart limits, CSRF origin validation for action POSTs, health/readiness endpoints, and graceful shutdown. In many other React stacks, these concerns are delegated to the hosting platform, custom server, reverse proxy, or adapter rather than exposed as a first-class runtime layer.
@lazarv/react-server treats server function invocation as hostile input before application code runs. Server function references are encrypted with AES-256-GCM capability tokens, support key rotation, and are decoded through configurable resource ceilings (maxRows, maxDepth, maxBytes, string/BigInt/stream limits) plus structural defenses against prototype pollution, forbidden path walks, hostile thenables, and forged callables. Next.js has meaningful Server Action defenses such as secure IDs, origin checks, closure encryption, and a body-size cap; TanStack Start has CSRF middleware and validators. The distinctive react-server behavior is the combined capability-token and hardened RSC reply-decoder layer as a first-class runtime boundary.
TanStack Start has the most direct server-function middleware model in this comparison: function middleware can wrap server functions with client-side logic, server-side logic, input validation, composition, and global registration. @lazarv/react-server does not currently expose a first-class TanStack-style per-function middleware chain. Its request middleware runs before server function dispatch and can short-circuit or annotate the request, while createFunction provides protocol-level per-argument parse/validate contracts before the handler runs. Cross-cutting per-function policy can still be composed with userland wrappers, but the first-class runtime primitive is the request middleware plus contract/decoder boundary, not a client/server function middleware pipeline. React Router middleware wraps route action/loader requests, which is useful but tied to the route action model rather than arbitrary RPC server functions, so it is also not first-class support for this specific row.
@lazarv/react-server has built-in OpenTelemetry integration that can automatically instrument HTTP requests, middleware, RSC/SSR rendering, server functions, cache lookups, server startup, and Vite dev hooks, plus built-in request, render, server function, and cache metrics. Telemetry dependencies are optional and lazy-loaded, so disabled telemetry resolves to no-op instrumentation. Next.js also has official OpenTelemetry instrumentation and framework spans. React Router exposes first-class instrumentation wrappers that apps wire into logging or tracing. TanStack Start documents observability patterns and manual/experimental OpenTelemetry setup, while Waku leaves this mostly to userland or the host platform.
Pages with "use client" in the file-system router are automatically client-only — navigation skips the server entirely. No configuration needed, and component state is preserved across navigations via React's <Activity> component.
Route params and search params can be validated with any schema library (Zod, ArkType, Valibot) or lightweight parse functions — the runtime detects the validation strategy automatically.
@lazarv/react-server offers two complementary data-fetching approaches: React Server Components with async/await (RSC as loaders), and typed resources — schema-validated, reference-identified data descriptors with .use() (suspense), .query() (imperative), .prefetch(), and .invalidate(). Resources use "use cache" as the caching runtime — no custom cache layer, no SWR boilerplate. Route-resource bindings enable parallel prefetching on navigation.
TanStack Router exposes route context as a first-class typed primitive for passing dependencies (auth, DB clients, etc.) down the route tree. @lazarv/react-server models the same problem space through typed resources, request context, and native modules — there is no separate route-context bag because resources already carry schema-validated, route-scoped data with full type safety.
@lazarv/react-server ships with integrated devtools (--devtools) that go beyond route inspection — they cover RSC payload, cache entries, routes, outlets, remote components, live components, workers, and server logs in a single panel. TanStack Router provides excellent router-focused devtools, but @lazarv/react-server's devtools cover the full server component runtime.
@lazarv/react-server uses named outlets (@sidebar, @content) rendered as typed props to layouts. This is functionally similar to Next.js parallel routes but with stronger typing — each outlet is a branded React element that prevents accidentally swapping outlets.
@lazarv/react-server intentionally does not support TanStack-style route masking. The visible browser URL, server request URL, matched route tree, RSC payload, route validation, resources, cache keys, outlets, and devtools state are expected to describe the same navigation state. Use rewrites, redirects, route groups, outlets, or search params when a URL needs a different presentation, without creating hidden client-only route identity.
@lazarv/react-server exposes navigation guards (useNavigationGuard, registerNavigationGuard) for client-side page-root navigation decisions, including back/forward and optional beforeUnload handling. Internally, route guard/registration components manage route registration, active visibility, route resources, loading skeletons, and Activity-based preservation. User effects should live in React effects, resources, middleware, server functions, or cache invalidation rather than router-object mount/unmount callbacks.
@lazarv/react-server hydration islands are initial-rendering boundaries that render server HTML immediately, store request-scoped island hydration data, and later hydrate as independent local outlets. This can work without a hydrated PAGE_ROOT. TanStack Start has deferred hydration-style behavior for suspended React subtrees, but that subtree still lives inside the page's React tree rather than becoming a separate island outlet with its own RSC payload. Astro is the closest architectural match outside this React/RSC comparison: it has a real island architecture for component-level hydration, but it is not an RSC local-outlet model. Other React frameworks can lazy-load client components or defer JavaScript in userland, but they do not provide this local-outlet island model as a first-class feature.
Waku is another RSC-native framework built on Vite, but takes a deliberately minimal approach. It provides basic file-based routing with layouts and RSC support, but lacks the typed routing system, search param handling, scroll restoration, middleware, and most advanced routing features. Waku's Link component supports basic scroll and prefetchOnEnter/prefetchOnView props, but most of its router API is still marked as unstable_. Waku is a good choice for simple RSC applications that don't need advanced routing.