> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nuxt/nuxt/llms.txt
> Use this file to discover all available pages before exploring further.

# Prerendering and Static Site Generation

> Learn how to prerender your Nuxt application at build time for improved performance and SEO using static site generation (SSG).

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.

<Note>
  Prerendering is powered by [Nitro](https://nitro.build), Nuxt's server engine, which provides crawl-based pre-rendering capabilities out of the box.
</Note>

## 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.

<Steps>
  <Step title="Run the generate command">
    Execute the generate command using your preferred package manager:

    <CodeGroup>
      ```bash npm theme={null}
      npx nuxt generate
      ```

      ```bash yarn theme={null}
      yarn nuxt generate
      ```

      ```bash pnpm theme={null}
      pnpm nuxt generate
      ```

      ```bash bun theme={null}
      bun x nuxt generate
      ```
    </CodeGroup>
  </Step>

  <Step title="Deploy the output">
    You can now deploy the `.output/public` directory to any static hosting service or preview it locally:

    ```bash theme={null}
    npx serve .output/public
    ```
  </Step>
</Steps>

### 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

<Warning>
  Pages that are not linked to a discoverable page can't be pre-rendered automatically. You'll need to configure these routes manually.
</Warning>

## 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:

```ts nuxt.config.ts theme={null}
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:

```ts nuxt.config.ts theme={null}
export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: ['/user/1', '/user/2'],
      ignore: ['/dynamic'],
    },
  },
})
```

### Combining with Crawl Links

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`:

```ts nuxt.config.ts theme={null}
export default defineNuxtConfig({
  nitro: {
    prerender: {
      crawlLinks: true,
      routes: ['/sitemap.xml', '/robots.txt'],
    },
  },
})
```

<Note>
  Setting `nitro.prerender` to `true` is equivalent to setting `nitro.prerender.crawlLinks` to `true`.
</Note>

### Using Route Rules

You can also configure prerendering using `routeRules` for fine-grained control:

```ts nuxt.config.ts theme={null}
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`:

```vue app/pages/index.vue theme={null}
<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>
```

<Note>
  To use `defineRouteRules` in page files, you must enable the `experimental.inlineRouteRules` option in your `nuxt.config`.
</Note>

This will be translated to:

```ts nuxt.config.ts theme={null}
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:

```vue app/pages/index.vue theme={null}
<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:

```ts nuxt.config.ts theme={null}
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:

```ts nuxt.config.ts theme={null}
export default defineNuxtConfig({
  nitro: {
    hooks: {
      'prerender:generate' (route) {
        if (route.route?.includes('private')) {
          route.skip = true
        }
      },
    },
  },
})
```

## Best Practices

<AccordionGroup>
  <Accordion title="When to use prerendering">
    Use prerendering for:

    * Marketing pages and landing pages
    * Blog posts and documentation
    * E-commerce product pages
    * Any content that doesn't change frequently
  </Accordion>

  <Accordion title="When not to use prerendering">
    Avoid prerendering for:

    * User-specific dashboards
    * Real-time data displays
    * Pages with authentication requirements
    * Content that changes frequently
  </Accordion>

  <Accordion title="Optimizing build times">
    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
  </Accordion>
</AccordionGroup>
