Index of every page on this site: llms.txt

Nuxt Routing and SEO

Structure Nuxt routes and pick per-path rendering so public content is available to crawlers.
Harlan Wilton8 mins read Published Updated
What you'll learn
  • Use stable, descriptive URLs. Both path segments and query parameters can identify indexable content
  • 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

Choose stable paths or query URLs that identify the page, 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

TopicWhat You'll Learn
URL StructureSlugs, hyphens, and keyword placement
PaginationSelf-referencing canonicals and paginated content indexing
Trailing SlashesConsistent URL formats and redirect configuration
Query ParametersFilters, tracking params, and canonical handling
Hreflang & i18nMultilingual sites, x-default, and return links
404 PagesSoft 404s, proper status codes, and crawl budget
Dynamic RoutesRoute params and Nuxt 4 SSR patterns
Internal LinkingHub and spoke architecture, link equity flow, orphan pages
Programmatic SEOFeature pages, comparison pages, alternatives at scale
Rendering ModesSSR, SSG, ISR, and Nuxt Islands compared

Rendering Strategy

Interaction to Next Paint (INP) is one of Google's Core Web Vitals: a page experience signal used by its ranking systems, alongside other signals. Match your rendering strategy to what each route needs:

StrategyBenefitBest For
Nuxt IslandsMinimal client JSStatic components (header, footer)
Edge RenderingCan reduce network distance; measure response timeGlobal audiences
SWR / ISRStatic speed with freshnessProduct catalogs, news feeds
Partial HydrationCan reduce client work; measure INPContent-heavy pages with widgets

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

export default defineNuxtConfig({
  routeRules: {
    '/blog/**': { isr: true }, // Requires a supported deployment preset
    '/products/**': { swr: 3600 }, // Stale-While-Revalidate
    '/dashboard/**': { ssr: false }, // Client-only (SPA)
    '/api/**': { cors: true }
  }
})

URL Structure Quick Reference

Both formats can identify indexable content:

✅ /products/electronics/laptop
✅ /products?category=electronics&item=laptop

Hyphens over underscores:

✅ /nuxt-routing-guide
❌ /nuxt_routing_guide

Lowercase, short URLs:

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

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

ProblemSolution
Inconsistent trailing slashesConfigure redirects
Pagination without canonicalsSelf-referencing canonicals
Infinite filter combinationsNoindex or block in robots.txt
Soft 404s returning 200Proper status codes
Orphan pages with no linksBuild internal linking structure

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. Smaller sites should keep sitemaps current and monitor index coverage in Google Search Console.

File-Based Routing

Nuxt creates routes automatically from the /pages directory:

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

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

This initial-load example requires your /api/posts/:slug endpoint returning title and excerpt, or404 for an absent post. Add route-change handling if the same component remains mounted:

<script setup lang="ts">
const route = useRoute()
const { data: post, error } = await useFetch<{ title: string, excerpt: string }>(`/api/posts/${encodeURIComponent(String(route.params.slug))}`)
if (error.value)
  throw error.value
if (!post.value)
  throw createError({ statusCode: 404, statusMessage: 'Post not found' })

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

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

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' }
  ]
})

Configure language metadata and baseUrl, then apply useLocaleHead(). Installing the module alone does not add the complete head tags:

Follow the module's current SEO setup for language tags, canonical URLs, and alternate links.

Read Hreflang & i18n for configuration, bidirectional links, and common mistakes.

Was this page helpful?