Search engines read URLs before content. /products/shoes ranks better than /products?category=shoes. /about and /about/ are different pages unless you configure otherwise.
Rendering mode determines whether crawlers see your content immediately (SSR/SSG) or must execute JavaScript first (SPA). Google can render JavaScript, but it's slower and less reliable than serving HTML directly.
Nuxt renders on the server by default, ensuring crawlers see your content immediately.
| Topic | What You'll Learn |
|---|---|
| URL Structure | Slugs, hyphens vs underscores, URL length, keyword placement |
| Pagination | Self-referencing canonicals, infinite scroll vs pagination, crawlable links |
| Trailing Slashes | Consistent URL formats, redirect configuration |
| Query Parameters | Filters, tracking params, canonical handling |
| Hreflang & i18n | Multilingual sites, x-default, return links |
| 404 Pages | Soft 404s, proper status codes, crawl budget |
| Dynamic Routes | Route params, per-route meta tags, SSR patterns |
| Rendering Modes | SSR vs SSG vs SPA, when to use each |
| Mode | Crawler Sees HTML | Best For |
|---|---|---|
| SSR (default) | Immediately | Dynamic content, personalization |
| SSG | Immediately | Blogs, docs, marketing pages |
| SPA | After JavaScript | Admin panels, authenticated apps |
Nuxt uses SSR by default. Configure rendering per route with routeRules in nuxt.config.ts:
export default defineNuxtConfig({
routeRules: {
'/blog/**': { prerender: true }, // SSG
'/dashboard/**': { ssr: false }, // SPA
'/api/**': { ssr: false } // Client-only
}
})
Google's JavaScript rendering has a second wave of indexing that delays content discovery. SSR avoids this delay.
Path segments over query parameters:
✅ /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.
Google allocates limited time to crawl your site. Poor URL structure wastes budget on duplicate or low-value pages.
Common crawl budget problems:
| Problem | Solution |
|---|---|
| Inconsistent trailing slashes | Configure redirects |
| Pagination without canonicals | Self-referencing canonicals |
| Infinite filter combinations | Noindex or block in robots.txt |
| Soft 404s returning 200 | Proper status codes |
Sites under 10,000 pages rarely need to worry about crawl budget. Large sites should monitor Google Search Console crawl stats.
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.
Each dynamic route needs unique meta tags:
<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 for SSR patterns, optional params, and common SEO issues.
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' }
]
})
The @nuxtjs/i18n module handles this automatically:
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
locales: ['en', 'fr'],
defaultLocale: 'en',
strategy: 'prefix_except_default'
}
})
Read Hreflang & i18n for configuration, bidirectional links, and common mistakes.