---
title: "Nuxt Routing and SEO"
description: "Structure Nuxt routes and pick per-path rendering so search engines can crawl, index, and rank every page."
canonical_url: "https://nuxtseo.com/learn-seo/nuxt/routes-and-rendering"
last_updated: "2026-07-16"
---

<key-takeaways>

- Use path segments (`/products/shoes`) instead of query parameters; they're easier for Google to crawl and rank
- Rendering mode determines whether crawlers see your content immediately (SSR/SSG) or need to execute JavaScript first (SPA)
- Nuxt route rules let you mix SSR, SSG, ISR, and SWR per path instead of picking one mode for the whole app
- Inconsistent trailing slashes and unbounded query parameters create duplicate content that wastes crawl budget

</key-takeaways>

Use path segments (`/products/shoes`) instead of query parameters (`/products?id=123`), and match rendering mode to what each route needs: static pages as SSG, dynamic pages as SSR, admin-only pages as SPA. Nuxt route rules let you mix all three per path instead of picking one mode for the whole app.

## Section Overview

<table>
<thead>
  <tr>
    <th>
      Topic
    </th>
    
    <th>
      What You'll Learn
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/url-structure">
        URL Structure
      </a>
    </td>
    
    <td>
      Slugs, hyphens, and keyword placement
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/pagination">
        Pagination
      </a>
    </td>
    
    <td>
      Self-referencing canonicals and paginated content indexing
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/trailing-slashes">
        Trailing Slashes
      </a>
    </td>
    
    <td>
      Consistent URL formats and redirect configuration
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/query-parameters">
        Query Parameters
      </a>
    </td>
    
    <td>
      Filters, tracking params, and canonical handling
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/i18n">
        Hreflang & i18n
      </a>
    </td>
    
    <td>
      Multilingual sites, x-default, and return links
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/404-pages">
        404 Pages
      </a>
    </td>
    
    <td>
      Soft 404s, proper status codes, and crawl budget
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/dynamic-routes">
        Dynamic Routes
      </a>
    </td>
    
    <td>
      Route params and Nuxt 4 SSR patterns
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/internal-linking">
        Internal Linking
      </a>
    </td>
    
    <td>
      Hub and spoke architecture, link equity flow, orphan pages
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/programmatic-seo">
        Programmatic SEO
      </a>
    </td>
    
    <td>
      Feature pages, comparison pages, alternatives at scale
    </td>
  </tr>
  
  <tr>
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/rendering">
        Rendering Modes
      </a>
    </td>
    
    <td>
      SSR, SSG, ISR, and Nuxt Islands compared
    </td>
  </tr>
</tbody>
</table>

## Rendering Strategy

Interaction to Next Paint (INP) is one of Google's Core Web Vitals: a [page experience signal](https://developers.google.com/search/docs/appearance/core-web-vitals) that its ranking systems reward, mainly as a tiebreaker between similarly relevant pages. Match your rendering strategy to what each route needs:

<table>
<thead>
  <tr>
    <th>
      Strategy
    </th>
    
    <th>
      Benefit
    </th>
    
    <th>
      Best For
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Nuxt Islands
    </td>
    
    <td>
      Minimal client JS
    </td>
    
    <td>
      Static components (header, footer)
    </td>
  </tr>
  
  <tr>
    <td>
      Edge Rendering
    </td>
    
    <td>
      Low TTFB
    </td>
    
    <td>
      Global audiences
    </td>
  </tr>
  
  <tr>
    <td>
      SWR / ISR
    </td>
    
    <td>
      Static speed with freshness
    </td>
    
    <td>
      Product catalogs, news feeds
    </td>
  </tr>
  
  <tr>
    <td>
      Partial Hydration
    </td>
    
    <td>
      Better INP
    </td>
    
    <td>
      Content-heavy pages with widgets
    </td>
  </tr>
</tbody>
</table>

Nuxt uses SSR by default. Mix strategies per route with route rules:

```ts
export default defineNuxtConfig({
  routeRules: {
    '/blog/**': { isr: true }, // Incremental Regeneration
    '/products/**': { swr: 3600 }, // Stale-While-Revalidate
    '/dashboard/**': { ssr: false }, // Client-only (SPA)
    '/api/**': { cors: true }
  }
})
```

## URL Structure Quick Reference

**Path segments over query parameters:**

```text
✅ /products/electronics/laptop
❌ /products?category=electronics&item=laptop
```

**Hyphens over underscores:**

```text
✅ /nuxt-routing-guide
❌ /nuxt_routing_guide
```

**Lowercase, short URLs:**

```text
✅ /blog/nuxt-seo
❌ /Blog/The-Complete-Guide-To-Nuxt-SEO-Optimization-2025
```

Read [URL Structure](/learn-seo/nuxt/routes-and-rendering/url-structure) for implementation details.

## Crawl Budget

Google allocates limited time to crawl your site. Poor URL structure wastes budget on duplicate or low-value pages.

**Common crawl budget problems:**

<table>
<thead>
  <tr>
    <th>
      Problem
    </th>
    
    <th>
      Solution
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Inconsistent trailing slashes
    </td>
    
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/trailing-slashes">
        Configure redirects
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      Pagination without canonicals
    </td>
    
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/pagination">
        Self-referencing canonicals
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      Infinite filter combinations
    </td>
    
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/query-parameters">
        Noindex or block in robots.txt
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      Soft 404s returning 200
    </td>
    
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/404-pages">
        Proper status codes
      </a>
    </td>
  </tr>
  
  <tr>
    <td>
      Orphan pages with no links
    </td>
    
    <td>
      <a href="/learn-seo/nuxt/routes-and-rendering/internal-linking">
        Build internal linking structure
      </a>
    </td>
  </tr>
</tbody>
</table>

Google's own guidance treats crawl budget as a concern mainly for sites with 10,000+ pages that update daily, or a million-plus pages that update weekly: see [managing crawl budget for large sites](https://developers.google.com/search/docs/crawling-indexing/large-site-managing-crawl-budget). Smaller sites should keep sitemaps current and monitor index coverage in [Google Search Console](https://search.google.com/search-console).

## File-Based Routing

Nuxt creates routes automatically from the `/pages` directory:

```text
pages/
  blog/
    [slug].vue       → /blog/:slug
  products/
    [category]/
      [id].vue       → /products/:category/:id
```

Generates `/blog/nuxt-seo-guide` and `/products/electronics/123`.

Each dynamic route needs unique meta tags:

```vue
<script setup lang="ts">
const route = useRoute()
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)

useSeoMeta({
  title: post.value.title,
  description: post.value.excerpt
})
</script>
```

Read [Dynamic Routes](/learn-seo/nuxt/routes-and-rendering/dynamic-routes) for SSR patterns, optional params, and common SEO issues.

## Multilingual Sites

Use hreflang tags to tell search engines which language version to show users:

```ts
useHead({
  link: [
    { rel: 'alternate', hreflang: 'en', href: 'https://example.com/en' },
    { rel: 'alternate', hreflang: 'fr', href: 'https://example.com/fr' },
    { rel: 'alternate', hreflang: 'x-default', href: 'https://example.com/en' }
  ]
})
```

The `@nuxtjs/i18n` module handles this automatically:

```ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: ['en', 'fr'],
    defaultLocale: 'en',
    strategy: 'prefix_except_default'
  }
})
```

Read [Hreflang & i18n](/learn-seo/nuxt/routes-and-rendering/i18n) for configuration, bidirectional links, and common mistakes.
