← Dashboard

Web Foundations · Reference

Meta-Frameworks & Routing

Next.js vs Vite, the landscape, routing · 8 min read

Meta-Frameworks & Routing

Status: reference Last updated: 2026-06-16 Scope: what a meta-framework is, why they exist, a deep look at Next.js and Vite (and why comparing them is a category mix-up), the wider landscape, and how routing works. Assumes the rendering vocabulary in web-app-concepts.md.


What is a meta-framework?

React, Vue, and Svelte are, at their core, view libraries — they turn state into UI. They deliberately leave out almost everything else a real application needs: routing, data loading, server rendering, bundling, environment config, deployment. A meta-framework is the layer built on top of a view library that supplies those missing pieces as one integrated, opinionated package.

            your app
   ┌───────────────────────────┐
   │  meta-framework            │  routing, data loading, SSR/SSG,
   │  (Next.js, SvelteKit, …)   │  endpoints, deploy adapters, build wiring
   ├───────────────────────────┤
   │  view library              │  React / Svelte / Vue — state → UI
   ├───────────────────────────┤
   │  build tool                │  Vite (or Turbopack/webpack) — dev server,
   │                            │  bundling, HMR
   └───────────────────────────┘

So "meta" = a framework around a framework. It answers the questions the view library leaves open: How do URLs map to screens? Where does data come from? Is this page server-rendered or static? How do I deploy it?

Without one, you assemble those answers yourself from separate libraries (a router + a data layer + a build config). With one, they're decided for you and wired together — less choice, less glue, more consistency.


Build tool vs meta-framework — Vite is not a meta-framework

The most common confusion (and the framing in the original question) is "Next.js vs Vite." They are different layers:

  • Vite is a build tool / dev server. It compiles and bundles your code, serves it in dev with instant HMR (native ES modules + esbuild prebundling), and produces an optimized production build (via Rollup, migrating to the Rust-based Rolldown). It knows nothing about routing, SSR, or your app's structure. (We use it under our own KB app — see the earlier deep-dive.)
  • Next.js is a meta-framework. It includes a build tool (now Turbopack), and adds routing, rendering modes, data loading, server endpoints, and deployment.

They're not alternatives at the same level. The reason people compare them is that the real decision is:

"Next.js (a batteries-included meta-framework)" vs "Vite + a router (a do-it-yourself stack)."

Tellingly, most meta-frameworks are built on Vite — SvelteKit, Nuxt, Astro, TanStack Start, SolidStart all use it as their underlying build tool. Next.js is the notable outlier with its own bundler. So Vite is less a competitor to these frameworks than the foundation underneath them.


Next.js — the deep dive

What it is: the dominant React meta-framework, made by Vercel. As of 2026 the current line is Next.js 16.x (16.2, early 2026).

Core pieces:

  • App Router (now the default, stable) — file-based routing built around React Server Components, layouts, and streaming. (The older Pages Router still exists for legacy apps.)
  • Server Components + Server Actions — render and mutate on the server with zero/minimal client JS for those parts; see react.md.
  • Every rendering mode — CSR, SSR, SSG, ISR, streaming, and Partial Prerendering ("Cache Components": a static shell with dynamic parts streamed in).
  • Turbopack — Rust bundler, now the default dev bundler (~10× faster HMR on large projects than webpack).
  • Deploy — runs anywhere Node runs, but is tuned for Vercel; some newer features land there first / are smoothest there.

Strengths: the most capable, most-resourced React platform; the default for new public-facing React apps; huge ecosystem and docs.

Weaknesses / watch-outs for a long-lived system:

  • Complexity & churn — the App Router / RSC model is powerful but a moving target; idioms have shifted repeatedly (Pages → App → Cache Components).
  • Vercel gravity — self-hostable, but the happy path tilts toward Vercel; weigh hosting independence for a 10-year system.
  • Heavier than you may need — for an authenticated internal SPA, much of Next.js's server machinery is overhead you don't use.

Vite — the role (recap)

Covered in depth earlier; in the meta-framework context the key points:

  • It's the build/dev engine, not a framework. You bring your own routing and data approach.
  • The canonical lightweight React stack is Vite + React Router (or TanStack Router) producing a CSR SPA — closest to a classic client-rendered app, trivial to self-host (static files + your .NET API).
  • It's the foundation under SvelteKit, Nuxt, Astro, TanStack Start, etc.

Choose "Vite + router" over a full meta-framework when you want a pure SPA, maximum control, minimal magic, and no Node server in production — a strong fit for internal line-of-business tools.


Next.js vs "Vite + router" — the real comparison

Next.js Vite + router (e.g. React Router v7 / TanStack)
Category Meta-framework Build tool + routing library (DIY stack)
Routing Built in (file-based) You add a router
SSR / SSG / streaming Built in, per route DIY (or none — usually CSR SPA)
Server Components Yes (App Router) No (unless you adopt a framework)
Data loading Integrated (server components, actions) Your choice (TanStack Query, loaders, fetch)
Build Turbopack (bundled) Vite (you configure)
Opinionation High (the framework decides) Low (you decide)
Production server Node server (or Vercel) for SSR None needed for a static SPA
Lock-in / hosting Tilts to Vercel Host static files anywhere
Best for Public, SEO-driven, full-stack React apps SPAs, internal tools, max control + self-host

For our context (internal, safety-adjacent, .NET backend), the Vite + router CSR SPA end of this table is usually the better-aged choice; Next.js earns its complexity mainly when public SEO / SSR is a hard requirement.


The wider landscape (others worth knowing)

Meta-framework View layer Built on Best for
Next.js React Turbopack/webpack Full-stack, SEO, the React default
React Router v7 React Vite The ex-Remix; loaders/actions, web-standards, progressive enhancement. Remix-as-a-name folded into RR v7; "Remix 3" is a separate, non-React project.
TanStack Start React Vite Type-safe, Vite-native React full-stack; rising as a Next.js alternative
SvelteKit Svelte Vite Leanest bundles; the one canonical Svelte stack — see svelte.md
Nuxt Vue Vite + Nitro Vue's Next.js; Nitro gives the most portable deploy (any host)
Astro Any (islands) Vite Content-first, minimal JS via islands; acquired by Cloudflare (Jan 2026)
SolidStart Solid Vite + Nitro Fine-grained reactive, very fast
Qwik (City) Qwik Vite Resumability — skips hydration for extreme first-load perf

Two infrastructure names that recur: Vite (the build tool under most of them) and Nitro (a portable server engine under Nuxt/SolidStart/others that deploys to almost any host). They're why "which framework" increasingly matters less for deployment than it used to.


Routing — purpose, effects, and types

Routing is the part of an app that maps the URL to what's shown and what data is loaded. It's often the single biggest thing a meta-framework provides — which is why it lives on this page.

What routing is for

  • Deep-linkable state — a URL captures where you are so it can be bookmarked, shared, and reloaded to the same place.
  • Browser integration — back/forward buttons, history, scroll restoration work correctly.
  • Navigation model — full page loads (server routing) vs in-place view swaps (client routing).
  • Code-splitting boundaries — routes are natural points to lazy-load only the JS a given screen needs.
  • Data-loading boundaries — modern routers attach which data to fetch to each route, so navigation and data stay in sync.
  • Layout composition — nested routes share persistent layouts (sidebars, shells) without re-rendering them on every navigation.

What it affects

UX (reload vs instant nav), SEO (server-routed URLs are individually indexable), bundle size (per-route splitting), data fetching, auth boundaries (guarding route subtrees), and how the app is deployed (static routes vs server routes).

Types of routing

By where navigation is handled:

  • Server-side routing (traditional / MPA) — every URL is a request to the server, which returns a full HTML page. Simple, great SEO, but full reloads.
  • Client-side routing (SPA) — JavaScript intercepts link clicks, swaps the view, and updates the URL via the History API — no full reload. Fluid, but the client owns navigation (see web-app-concepts.md).
  • Hybrid / isomorphic — what meta-frameworks do: the first page is server-rendered (fast paint, SEO), and subsequent navigations are client-side (fluid). Best of both, at the cost of complexity.

By how routes are declared:

  • File-based routing — the file/folder structure is the route table (routes/blog/[slug]/+page.svelte/blog/:slug). Used by SvelteKit, Next.js, Nuxt, Astro. Convention over configuration; easy to scan.
  • Config / code-based routing — routes declared explicitly in code as a tree of objects/components. Classic React Router; more flexible, more boilerplate. (React Router v7 now offers both styles.)

Common routing features (any modern router):

  • Dynamic segments/:id / [id] capture parameters.
  • Nested routes & layouts — shared shells around child routes.
  • Catch-all / splat/* or [...rest] for arbitrary depths.
  • Route guards / loaders — run auth checks or fetch data before a route renders.

How this lands for our choice

  • Svelte → routing is not a decision: SvelteKit's file-based router is built in and canonical.
  • React → routing is a choice: Next.js (built-in file router), React Router v7 (the ex-Remix, config or file-based), or TanStack Router (type-safe). This is another instance of React's "assemble the stack" tax versus Svelte's single answer — see react-vs-svelte.md.

Sources