Skip to main content
Nuxt allows you to statically render select pages from your application at build time. When you prerender pages, Nuxt serves the prebuilt pages when requested instead of generating them on the fly.
Prerendering is powered by Nitro, Nuxt’s server engine, which provides crawl-based pre-rendering capabilities out of the box.

Crawl-Based Pre-rendering

Use the nuxt generate command to build and pre-render your application using the Nitro crawler. This command is similar to nuxt build with the nitro.static option set to true, or running nuxt build --prerender. The crawler will build your site, stand up a Nuxt instance, and by default prerender the root page / along with any pages it links to, recursively following all discoverable links.
1

Run the generate command

Execute the generate command using your preferred package manager:
npx nuxt generate
2

Deploy the output

You can now deploy the .output/public directory to any static hosting service or preview it locally:
npx serve .output/public

How the Nitro Crawler Works

The Nitro crawler follows this process:
  1. Load HTML - Loads the HTML of your application’s root route (/), any non-dynamic pages in your ~/pages directory, and any other routes in the nitro.prerender.routes array
  2. Save output - Saves the HTML and payload.json to the ~/.output/public/ directory to be served statically
  3. Find links - Finds all anchor tags (<a href="...">) in the HTML to navigate to other routes
  4. Repeat - Repeats steps 1-3 for each anchor tag found until there are no more anchor tags to crawl
Pages that are not linked to a discoverable page can’t be pre-rendered automatically. You’ll need to configure these routes manually.

Payload Extraction

Nuxt generates _payload.json files alongside HTML for:
  • Prerendered routes (at build time)
  • ISR/SWR routes (on first request)
Payloads contain serialized data from useAsyncData and useFetch. During client-side navigation, these cached payloads are loaded instead of re-fetching data. For dynamic routes like pages/[...slug].vue, configure route rules:
nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/**': { isr: true },
  },
})

Selective Pre-rendering

You can manually specify routes that Nitro will fetch and pre-render during the build, or ignore routes that you don’t want to pre-render.

Configuring Routes in nuxt.config

Specify routes to prerender and routes to ignore in your nuxt.config.ts file:
nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/user/1', '/user/2'],
      ignore: ['/dynamic'],
    },
  },
})
Combine manual route specification with the crawlLinks option to pre-render routes that the crawler can’t discover, like your /sitemap.xml or /robots.txt:
nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    prerender: {
      crawlLinks: true,
      routes: ['/sitemap.xml', '/robots.txt'],
    },
  },
})
Setting nitro.prerender to true is equivalent to setting nitro.prerender.crawlLinks to true.

Using Route Rules

You can also configure prerendering using routeRules for fine-grained control:
nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Set prerender to true to configure it to be prerendered
    '/rss.xml': { prerender: true },
    // Set it to false to configure it to be skipped for prerendering
    '/this-DOES-NOT-get-prerendered': { prerender: false },
    // Everything under /blog gets prerendered as long as it
    // is linked to from another page
    '/blog/**': { prerender: true },
  },
})

Page-Level Configuration

As a shorthand, you can configure prerendering directly in a page file using defineRouteRules:
app/pages/index.vue
<script setup>
// Set at the page level
defineRouteRules({
  prerender: true,
})
</script>

<template>
  <div>
    <h1>Homepage</h1>
    <p>Pre-rendered at build time</p>
  </div>
</template>
To use defineRouteRules in page files, you must enable the experimental.inlineRouteRules option in your nuxt.config.
This will be translated to:
nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },
  },
})

Runtime Prerender Configuration

prerenderRoutes Function

You can use prerenderRoutes at runtime within a Nuxt context to add more routes for Nitro to prerender:
app/pages/index.vue
<script setup>
prerenderRoutes(['/some/other/url'])
prerenderRoutes('/api/content/article/my-article')
</script>

<template>
  <div>
    <h1>This will register other routes for prerendering when prerendered</h1>
  </div>
</template>

prerender:routes Nuxt Hook

This hook is called before prerendering to register additional routes:
nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    async 'prerender:routes' (ctx) {
      const { pages } = await fetch('https://api.some-cms.com/pages').then(
        res => res.json(),
      )
      for (const page of pages) {
        ctx.routes.add(`/${page.name}`)
      }
    },
  },
})

prerender:generate Nitro Hook

This hook is called for each route during prerendering, allowing fine-grained handling:
nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    hooks: {
      'prerender:generate' (route) {
        if (route.route?.includes('private')) {
          route.skip = true
        }
      },
    },
  },
})

Best Practices

Use prerendering for:
  • Marketing pages and landing pages
  • Blog posts and documentation
  • E-commerce product pages
  • Any content that doesn’t change frequently
Avoid prerendering for:
  • User-specific dashboards
  • Real-time data displays
  • Pages with authentication requirements
  • Content that changes frequently
For large sites:
  • Use selective pre-rendering to limit the number of routes
  • Consider using ISR (Incremental Static Regeneration) for frequently updated content
  • Leverage the ignore option to skip unnecessary routes