Next.js
Choose it if you want the largest ecosystem, or one app on the most-used React framework.
Not if several deployed apps should share one backend and one login without wiring it yourself.
Where Devora.js stands next to the tools you're probably weighing it against — including where they're ahead. Speed numbers live on Performance.
Devora.js rows: @devorajs/core 0.3.5, checked October 16, 2026Other frameworks: checked October 16, 2026
Next.js, React Router v8 (framework mode — formerly Remix), SvelteKit and Astro. Each topic below has its own table; pick which frameworks to show, and on a phone each feature becomes a card.
Every route says how it renders, in its own file. Choosing a mode per route is not unique to Devora.js — the table below shows who else does it. The narrow claim here is only that the choice is one explicit line in the route file.
ssrThe loader runs on every request and the page is rendered fresh.
Use it for: Per-user or per-request data, anything behind a login.
export const renderMode = "ssr";The default for a route that exports nothing (unless the app sets another default).
ssgRendered once during devora build and served as static HTML.
Use it for: Content that does not change per request: docs, marketing, blog posts.
export const renderMode = "ssg";A dynamic route needs getStaticParams(). In dev it renders live per request; it is pre-rendered only by a production build.
csrThe server sends an empty shell; the component mounts in the browser.
Use it for: Pages that only make sense in a browser, behind your own client data layer.
export const renderMode = "csr";The loader never runs, and the page needs the client bundle to show anything. Import from @devorajs/core/client.
isrLike ssg, but regenerated once a revalidate window has passed.
Use it for: Mostly static content that should refresh on a schedule.
export const renderMode = "isr"; export const revalidate = { seconds: 3600 };Reliable under a long-lived Node server. On Vercel/Netlify the function's filesystem is not guaranteed to persist, so ongoing regeneration there has not been verified.
streamingThe shell is sent at once; island content streams in as it resolves.
Use it for: A page with one slow section you do not want the whole response to wait for.
export const renderMode = "streaming";GET only (no action). Delivered as one buffered response on Netlify; not verified on a live deployment elsewhere.
| Feature | Next.js | React Router | SvelteKit | Astro | |
|---|---|---|---|---|---|
| Render mode per route | |||||
ssr | Built inrenderMode = "ssr" in the route file. | Built inDynamic rendering of a route. | Built inssr: true; an app-wide setting. | Built inThe default; export const ssr per page. | Built inprerender = false per page, or output: 'server'. |
ssg | Built inrenderMode = "ssg" and getStaticParams(). | Built inPrerendered; generateStaticParams for dynamic routes. | Built inprerender() in config lists the URLs. | Built inexport const prerender = true per page or layout. | Built inThe default; prerender = true per page. |
csr | Built inrenderMode = "csr"; the loader never runs. | PartialClient Components, or a single-page-app setup; not a per-route mode. | Built inssr: false (SPA mode, app-wide); clientLoader per route. | Built inexport const ssr = false per page or layout. | Not verifiedClient islands exist; a whole-page client mode was not checked. |
isr | Built inrevalidate = { seconds }; not verified on serverless. | Built inexport const revalidate = 60; per-instance cache unless you add a shared handler. | Not built inNot described on the pages checked. | PartialOnly through adapter-vercel's isr option. | PartialOnly through the Vercel adapter's isr option. |
streaming | Built inrenderMode = "streaming"; GET only; buffered on Netlify. | Built inSuspense and loading.js. | Built inReturn promises from loaders; Await in Suspense. | Built inPromises from a server load; buffered where the platform cannot stream. | Built inHTML streaming in on-demand rendering. |
Checked against each framework's own documentation on October 16, 2026; a cell says "Not verified" where that page was not checked. Sources: Next.js: Incremental Static Regeneration · Next.js: Streaming · React Router: Rendering strategies · React Router: Streaming with Suspense · SvelteKit: Page options · SvelteKit: Loading data (streaming) · SvelteKit: adapter-vercel (ISR) · Astro: On-demand rendering · Astro: Vercel adapter (ISR). Next.js's ssr, ssg and csr cells are read from the two Next.js pages above and the Next.js docs they link to.
| Feature | Next.js 16 | React Router v8 | SvelteKit 3 | Astro 7 | |
|---|---|---|---|---|---|
| Per-route rendering | |||||
| Render mode chosen per route | Built inssr ssg csr isr streaming, one export in the route file | Built inStatic by default, dynamic when a route uses request data; revalidate and Suspense per route | PartialSSR and SPA mode are app-wide (ssr in config); pre-rendering lists URLs | Built inprerender, ssr, csr exports per page or layout | Built inprerender per page; output sets the default |
Catch-all routes ([...slug]) | Built inPages and API routes; ctx.catchAll.slug is the array (since 0.3.4) | Built in | Built inSplat routes: "*"; the rest is params["*"] | Built inRest parameters, [...path] | Built inRest parameters, [...path] |
| Query string and headers in data loading | Built inctx.url, ctx.headers, ctx.ip | Built in | Built in | Built in | Built in |
| Pre-rendered pages: validators and compression | Served from memory with an ETag (304 on a repeat visit) and brotli/gzip under devora start; 64 MB total, 2 MB per file, checked against the disk once a second | ||||
Honest note: explicit render-mode selection isn't unique to Devora.js — SvelteKit and Astro do it per route, and Next.js 16 closed most of the gap. Incremental regeneration is built in on Next.js and only a platform option elsewhere; Devora.js's version is the least battle-tested on serverless hosts.
The reason Devora.js exists. Turborepo and Nx are monorepo task runners rather than frameworks, so a "—" or "Not its job" cell is not a knock against them.
| Feature | Next.js (Multi-Zones) | Turborepo / Nx | Others | |
|---|---|---|---|---|
| Several apps in one project | ||||
| Multiple apps, one repo | Built inOne devora.config.ts; each app deploys separately, on its own domain | PartialSeparately deployed apps served under one domain, routed by rewrites | Built inThis is their core purpose | Not built inNot a first-class concept |
| Navigating between apps | Full page load (separate apps) | Hard navigation between zones, soft within one | Not its jobNot a routing tool | Not its job |
| One backend shared by every app | Built inOne packages/backend by default | PartialEach zone has its own Route Handlers; share code as a package | Not built inYou wire the backend yourself | Not its job |
| One login across apps | Built inEvery shared app accepts the same session; cookie.domain shares the browser login across subdomains | PartialNo sessions built in, but zones share one domain, so a cookie-based auth library carries across | Not built inYou build it yourself | Not its job |
| Build caching and task orchestration | Not built inNot Devora.js's job | Not its job | Built inTheir real strength | Not its job |
Honest note: Turborepo and Nx solve "build this repo full of apps fast"; Devora.js solves "these apps share a backend and a session system out of the box". You could use Turborepo and Devora.js together. Multi-Zones' one-domain model gets browser cookie sharing for free; Devora.js shares the login across subdomains only when shared.sessions.cookie.domain is set.
| Feature | Next.js 16 | React Router v8 | SvelteKit 3 | Astro 7 | |
|---|---|---|---|---|---|
| Sessions | |||||
| Server-side sessions built in | Built inOpaque IDs in a store you provide, revocable | Not built inA cookies API; the docs recommend an auth or session library | Built increateCookieSessionStorage, createSessionStorage, per route in loaders and actions | Not built inCookies in the handle hook; sessions are your code or a library | Built inSessions API since Astro 5.7; needs a storage driver |
| One session as cookie and Bearer token | Built inOne primitive, revoked on both at once | Not built in | Not built in | Not built in | Not built in |
| CSRF protection on by default | Built inFor cookie sessions; ctx.verifyCsrf() per action | PartialServer Actions check Origin; allowed origins are configurable | Not verified | PartialOrigin check on form posts | PartialOrigin check on form posts |
Honest note: built-in sessions aren't unique (React Router, Astro). The narrow claim: one session that works as an HttpOnly cookie and as a Bearer token, revoked on both at once, shared by every app in a project. Checking who someone is stays your code: Devora.js ships no auth provider, and none of the others is a replacement for one either.
Express, Fastify and NestJS, compared on what an API needs.
| Feature | Express 5 | Fastify 5 | NestJS 12 | |
|---|---|---|---|---|
| API behavior, defaults only | ||||
| Uncaught errors become JSON | Built inReal message hidden in production | Not built inHTML error page, message hidden in production | PartialJSON, but the raw error message is sent even in production | Built inJSON, message hidden |
| Unmatched route is a JSON 404 | Built inUnder /api | Not built inHTML Cannot GET … page | Built in | Built in |
| Wrong HTTP method is a 405 | Built inWhen the route exports methods | Not built in404 | Not built in404 | Not built in404 |
Tested directly in production mode with defaults only (October 16, 2026): Express 5.3.0, Fastify 5.12.7, NestJS 12.1.3 and Devora.js 0.3.5.
| Feature | Express 5 | Fastify 5 | NestJS 12 | |
|---|---|---|---|---|
| Built in, or bring your own | ||||
| CORS | Built incors in app.config.ts | Use a librarycors package | Use a libraryOfficial plugin (@fastify/cors) | Built inapp.enableCors() |
| File uploads (multipart) | PartialPage forms: File objects in action; API routes parse the body themselves | Use a librarymulter | Use a libraryOfficial plugin (@fastify/multipart) | Built inFileInterceptor (Multer, in @nestjs/platform-express) |
| Validation | Use a libraryDocumented Zod pattern | Use a library | Built inJSON Schema (Ajv) per route | Built inValidationPipe (class-validator) |
| Rate limiting | Use a libraryDocumented pattern | Use a library | Use a libraryOfficial plugin (@fastify/rate-limit) | Use a libraryOfficial module (@nestjs/throttler) |
| WebSockets | Use a libraryA separate realtime server (Socket.IO) works; ws works through a small wrapper around createNodeServer; server-sent events from an API route do not work yet: Live updates (WebSockets) | Use a library | Use a libraryOfficial plugin (@fastify/websocket) | Built inGateways in @nestjs/websockets (socket.io or ws) |
| Background jobs | Use a libraryBullMQ with Redis and a worker, a SQLite queue with a worker, and node-cron were tested on one Node server; not verified on Vercel or Netlify: Background jobs | Use a library | Use a library | Use a libraryOfficial modules (@nestjs/bullmq, needs Redis; @nestjs/schedule) |
| Dependency injection | Not built inBy design | Not built in | Not built in | Built inCore feature |
Each row was checked against the framework's documentation on October 16, 2026. "Use a library" includes the official packages each project maintains.
Honest note: NestJS and Fastify are more complete "batteries included" backend frameworks today. Devora.js's backend is closer to Express's minimalism, with a JSON error contract, method checks and CORS that Express doesn't give you by default. For WebSockets and background jobs it documents tested patterns, not built-ins: Live updates (WebSockets), Background jobs.
Devora.js is new and small. npm downloads for one full week, Sep 28, 2026 – Oct 4, 2026:
Per State of JS 2025 (the most recent edition): Next.js leads meta-framework usage but is losing satisfaction; Astro ranks highest on satisfaction, 39 points ahead of Next.js. On the backend side, Express leads usage with NestJS growing; Hono tops satisfaction (outside this page's scope, but worth knowing). Pick Devora.js for what it does differently, not for maturity.
As of @devorajs/core@0.3.5, checked in its source:
Set-Cookie; responses are sent in one piece, so there are no server-sent events.streaming is GET-only, and on Netlify it arrives as one buffered response.isr regeneration on Vercel/Netlify's serverless filesystem hasn't been verified; it is reliable under a long-lived Node server.devora start needs a restart for changed route code.Build time, requests/second, memory and JavaScript sent, measured against Next.js, Astro, SvelteKit and React Router on the same pages: see Performance.
Choose it if you want the largest ecosystem, or one app on the most-used React framework.
Not if several deployed apps should share one backend and one login without wiring it yourself.
Choose it if you build a content-heavy site with little client JavaScript by default.
Not if you need a shared login and backend across several apps.
Choose it if you need a mature backend today: DI, validation, WebSockets, jobs.
Not if you also want server-rendered React pages in the same project.
Choose it if several apps should share one backend and one login and deploy separately, and a pre-1.0 framework is fine.
Not if you need the largest ecosystem, a long track record, or built-in WebSockets and jobs.