Choosing Per‑Route Rendering Modes in Nuxt 3 with Route Rules
Learn how to use Nuxt 3 Route Rules to serve SSR, SSG, or CSR per route, improve FCP and SEO, and avoid common pitfalls.
16 Dec 2025, 01:05 UTC

Use Route Rules to choose rendering mode per route
Nuxt 3 lets you decide how each URL is rendered by using Route Rules. Instead of forcing the whole app into SSR, SSG, or CSR, you can assign a mode per route (or pattern) and let Nuxt's Nitro server handle the rest.
How Route Rules work in Nuxt 3
When Nuxt builds the application, the routeRules object is read by Nitro. For each incoming request Nitro checks the URL against the defined patterns and selects the corresponding rendering strategy:
ssr: true– render the page on the server for every request (traditional SSR).isr: truewithswr– generate a static HTML file at build time and re‑validate it after the specified seconds (incremental static regeneration).spa: true– skip server rendering and send a minimal HTML shell that hydrates on the client (pure CSR).
The selected mode influences what is sent in the initial HTML response, which directly affects First Contentful Paint (FCP) and SEO because crawlers see the fully rendered markup for SSR/SSG routes.
Worked configuration
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { ssr: true },
'/blog/**': { isr: true, swr: 3600 },
'/dashboard/**': { spa: true }
}
})
In this example:
- The homepage (
/) is always rendered on the server. - Any blog post under
/blog/is statically generated and refreshed every hour. - The dashboard area (
/dashboard/) is treated as a single‑page application, sending only the app shell to the browser.
Limits and common mistakes
- Route Rules are processed by the Nitro server; during
nuxt devthe dev server may fallback to SSR for all routes, so test the rules in a production‑like build (nuxt build && nuxt start). - Dynamic routes with parameters must use the correct glob syntax;
/posts/[slug]should be matched with/posts/**or an explicit param pattern. - Accessing browser‑only globals (
window,document) inside a component that is rendered on the server will throw an error. Move such code to aonMountedhook or create a.server.vuecomponent for server‑only logic. - If you mix SSR and CSR on the same page (for example, using
spa: trueon a route but also rendering server‑only data), ensure the HTML produced by the server matches the client‑side hydration tree; otherwise you will see hydration mismatch warnings.
Verification steps
- Disable JavaScript in the browser (Chrome DevTools → Settings → Disable JavaScript) and reload the page. Routes configured with
ssrorisrshould still display their full content, whilesparoutes will show only the fallback shell. - Open the Network tab, filter by
doc, and inspect the first HTML response. For SSR/SSG routes you should see the complete markup; for CSR routes you will see a minimal<div id="__nuxt"></div>‑like skeleton. - With JavaScript enabled, open the console and look for the message
Hydration completed(Nuxt 3 logs this after successful hydration) or the absence of hydration‑mismatch warnings.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.