Guide Nuxt SEO

«Nuxt ships server-side rendering by default, but that's a per-route setting, not a guarantee — full HTML to crawlers only on routes that keep it. Rendering modes, useSeoMeta(), the @nuxtjs/seo toolkit, hydration and Nitro caveats, Core Web Vitals, and the mistakes that quietly cost you.» _(Traduction)_ (Résumé en français du champ description : le texte source est conservé pour relecture francophone.)

Première publication : 26 juin 2026 · Dernière mise à jour : 3 août 2026 · Avancé
1 indice probant sur cette page

«Nuxt server-renders pages by default, so a route that keeps that default gives crawlers a complete HTML document instead of the empty shell a plain Vue SPA ships — but it's a per-route setting: routeRules or a global ssr:false can flip any route to CSR, so verify the actual route rather than assuming from the framework name. The foundational decision is rendering mode per route — SSR (default), SSG via nuxt generate, or hybrid route rules — because meta tags, schema, and sitemaps all come after that. Use useSeoMeta() for meta, treat Harlan Wilton's @nuxtjs/seo bundle as an optional third-party toolkit (not Nuxt core) for robots/sitemap/OG/schema/canonical, never reach for dynamic rendering (Google deprecated it), verify hydration/payload and Nitro deployment-preset/cache behavior independently of server HTML, and remember that AI-crawler rendering contracts vary by provider — SSR/SSG puts content in raw HTML and maximizes coverage.» _(Traduction)_ (Résumé en français du champ tldr : le texte source est conservé pour relecture francophone.)

TL;DR — Nuxt’s par défaut est rendu côté serveur, donc a route que garde que par défaut obtient a complet DOM au lieu de le vide shell a plain Vue SPA ships — mais c’est a per-route résultat: ssr: false or a routeRules override peut turn quelconque route dans CSR or hybrid, donc tester le réel route, pas le project nom. Rendu stratégie est le foundational décision — SSR (par défaut), SSG (nuxt generate), or hybrid routeRules — parce que meta, schema, et sitemaps tout come après il. Utiliser useSeoMeta() pour meta balises (useHead() pour le rest de le head, serveur-seulement variants quand vous ne pas besoin reactivity), et treat Harlan Wilton’s @nuxtjs/seo bundle as an optional tiers toolkit pour robots/sitemap/OG/schema/canonical — pas partie de Nuxt core, et pas proof son sortie est correct jusqu’à vous vérifier il. Jamais utiliser dynamic rendu (Google deprecated il). AI-robot rendu varies par provider — SSR/SSG maximizes raw-HTML coverage. Au-delà le initial HTML, vérifier hydration/payload, Nitro deployment presets et mise en cache, et direct HTTP status independently — serveur HTML alone ne fait pas prove quelconque de ceux. Le usual JS-SEO règles encore appliquer: réel <a href> liens, ne pas bloquer JS/CSS, watch rendu vs. raw HTML.

Nuxt is Vue’s réponse to the SPA problem

Vue, par itself, ships a application monopage: an HTML shell plus JavaScript que construit le DOM dans le navigateur. Nuxt est le meta-framework on top de Vue (running on le Nitro serveur moteur dans Nuxt 3, avec Nuxt 4 suivant dans 2025), et son entier raison pour existing — depuis an SEO standpoint — est que il renders on le serveur par par défaut. Chaque page arrives as a fully-formed HTML document, qui est exactly ce que Googlebot veut à lire sans having à execute JavaScript premier. Plain Vue SEO est son propre topic avec son propre échec modes; ici Je’m assuming vous avez picked Nuxt precisely donc vous ne pas ont à fight le SPA problème.

Ce est le même point Je faire à propos de JavaScript généralement: “quelconque kind de SSR, static rendu, et prerendering setup est going à être fine pour moteur de recherches. Gatsby, Suivant, Nuxt, etc., sont tout great.” Nuxt’s defaults sont pointed le correct façon. La plupart Nuxt SEO problèmes sont personnes turning ceux defaults off, or layering mistakes on top de les.

Rendu stratégie est le foundation — decided per route, pas per project

Avant meta balises, avant schema, avant sitemaps, le question que decides tout est comment fait le HTML obtenir produced pour ce spécifique route? Nuxt documents universal (serveur) rendu as le app-wide par défaut, mais que par défaut n’est pas a route-level guarantee: a mondial ssr: false switches le entier app à client rendu, et routeRules peut assign a différent mode à quelconque URL modèle. “Ce est a Nuxt app” indique vous rien à propos de comment un particulier page renders — vous ont à vérifier le route. Nuxt donne vous five strategies:

ModeHow vous définir itSEO impactMeilleur pour
Universal / SSRPar défaut (ssr: true)Excellent — complet HTML every requêteDynamic, personalized content
Static / SSGnuxt generateExcellent — HTML construit at deploy tempsBlogs, docs, marketing
HybridrouteRules per routeExcellent — mix per routeGrand mixed-content sites
SPA / CSRssr: falsePoor pour indexé contentDashboards, admin panels
Edge-sideDeployment targetExcellent — low TTFBGlobal performances

Le official Nuxt docs sont blunt à propos de pourquoi rendu côté client est le incorrect choice pour contenu: “Indexation et updating le contenu delivered via rendu côté client takes plus temps”, whereas avec serveur (universal) rendu “web robots d’exploration peut directement indexer lune page’s contenu.” Preuve à l’appui de cette affirmation Nuxt documents that universal rendering delivers HTML content immediately and allows crawlers to index it directly. Portée : Nuxt rendering; no indexing guarantee. Niveau de confiance : élevé · Vérifié : Nuxt: Rendering modes (Nuxt rendu docs.) CSR (ssr: false) est positioned pour back-office, dashboards, et games — pas n’importe quoi vous vouloir indexé.

Hybrid rendu est le power déplacer pour grand sites. Route règles dans nuxt.config.ts let vous définir le rendu et mise en cache mode per URL modèle:

routeRules: {
  '/blog/**':     { prerender: true },        // SSG for the blog
  '/product/**':  { swr: 3600 },              // ISR-style: regenerate hourly
  '/admin/**':    { ssr: false },             // SPA for the admin area
  '/checkout/**': { ssr: true },              // always-fresh SSR
}

swr (stale-tandis que-revalidate) et isr (incremental static regeneration) generate une page statically alors refresh il dans le background — ideal pour élevé page-count e-commerce or news où a complet rebuild on chaque modifier n’est pas practical. Nuxt Islands (<NuxtIsland>) rendre components sans shipping client-side JavaScript, cutting hydration coût et helping INP — le Core Web Vital c’est la plupart souvent le problème on Nuxt apps.

Comment vérifier ce que vous en réalité shipped: View Source montre le raw HTML le serveur sent; si votre contenu est là, vous êtes serveur-rendu. DevTools’ Elements panel montre le rendu DOM. Et GSC’s Inspection d’URL outil montre ce que Google en réalité récupéré et rendu — le source de truth. ne pas confiance “il semble fine dans mon navigateur.”

Comment Googlebot handles a Nuxt app

Google processes quelconque JavaScript app dans three phases — explorer, rendre, indexer — et le catch est timing: rendu se produit dans a queue, pas instantly. As Je put il dans mon JavaScript SEO guide, le renderer est patient — “là est aucun fixed timeout pour le renderer… c’est vraiment patient, et vous ne doit pas être concerned.” Mais patient n’est pas le même as rapide pour fresh contenu. Si vous ship a client-rendu page, votre contenu ne fait pas exist pour Google jusqu’à que rendre wave exécute; SSR et SSG fermer que gap parce que le HTML est complet on le premier récupérer.

Deux plus choses matter à scale. Rendu JavaScript est expensive — depuis mon 2019 JavaScript SEO talk (Ungagged), explorer coûts go up par roughly 20× une fois Google a à rendre (directional, mais le order de magnitude encore holds). Et Google takes le la plupart restrictive directive à travers raw et rendu HTML — donc a noindex injected par JavaScript va win over an index dans le raw HTML, et vice versa. A canonical injected via JavaScript est respected seulement si il y a aucun canonical dans le raw HTML déjà. Garder votre robots et canonical signaux dans le serveur-rendu HTML, qui Nuxt fait pour vous quand SSR est on.

The AI-crawler reality

Ce est le 2026 wrinkle. AI robots d’exploration — GPTBot, ClaudeBot, PerplexityBot, et le rest — généralement ne pas execute JavaScript à tout. Ils indexer le raw HTML et rien sinon. Donc a client-rendu Nuxt page est effectively invisible à AI réponse moteurs. SSR or SSG n’est pas simplement meilleur pour Google ici; c’est le price de entry pour réponse moteur optimization aussi. Si vous vouloir votre contenu cited par ChatGPT, Perplexity, or Claude, il a à être dans le HTML on premier récupérer.

Au-delà le initial HTML: payload, hydration, et code d’états

Getting serveur HTML avec votre contenu dans il est necessary mais pas sufficient — plusieurs choses peut encore go incorrect downstream de que premier réponse, et “Je vérifié View Source” ne fait pas cover les:

  • Payload et hydration. Universal rendu sends le HTML et a serialized données payload le client utilise à hydrate — attach event listeners et pick up où le serveur left off — sans re-fetching. Serveur HTML looking correct ne fait pas prove hydration succeeded, que client navigation reproduces le même contenu, or que le payload n’est pas stale. Si une page feels fine on premier charger mais breaks après a client-side route modifier, c’est a hydration/payload problème, pas a rendu-mode problème.
  • <ClientOnly> et navigateur-seulement contenu. Wrapping quelque chose dans <ClientOnly> — courant pour navigateur-API-dependent widgets — signifie c’est absent depuis le serveur réponse même on an otherwise-universal route. Si votre principal contenu, a clé lien, or votre meta balises fin up à l’intérieur a client-seulement boundary, robots d’exploration et AI bots que seulement lire le raw HTML miss il, regardless de votre rendu mode paramètre. Inspect le réel réponse, pas simplement le rendu mode config.
  • Code d’états et redirections ne sont pas self-certifying. A Nuxt erreur page rendu dans le navigateur, or a navigateTo()/composable-driven redirection, ne fait pas par itself prove ce que HTTP status le direct serveur réponse sent. Google’s guidance est explicit que meaningful code d’états matter pour exploration et indexation — confirmer le réel header avec curl -I, pas ce que le client-rendu erreur page displays.

None de ce est an argument contre universal rendu — c’est le reminder que “le HTML est serveur-rendu” est le premier vérifier, pas le dernier un.

Nitro, deployment presets, et cache boundaries

Nuxt’s serveur sortie est construit par Nitro, et Nitro compiles differently selon le deployment preset vous cible (Node serveur, Cloudflare, Vercel, Netlify, static, et others). Que matters pour le SEO parce que presets et adapters peut differ dans runtime APIs disponible, mise en cache behavior, streaming prise en charge, regional deployment, et filesystem accès — a route règle or serveur handler que fonctionne sous un preset n’est pas guaranteed à behave identically sous un autre. Deux consequences worth testing explicitly plutôt que assuming:

  • Cache keys et invalidation sont route-spécifique, pas automatic. swr et isr route règles cache et regenerate sortie, mais a incorrect cache clé, manquant invalidation, or a mise en cache header définir par votre deployment plateforme peut servir stale, personalized, or inconsistent HTML à robots d’exploration. Vérifier le réel réponse age et quelconque Cache-Control/Age headers on a actif URL, pas simplement le routeRules config.
  • Production parity n’est pas guaranteed par staging behavior. A route rendu correctement dans local dev or a preview deployment ne fait pas confirmer le production preset produces le même sortie — serveur routes, redirections, et erreur handling actif dans Nitro’s serveur couche, et que couche est le partie la plupart probable à differ par cible. Tester le production URL directement après quelconque deployment modifier, le même façon vous’d vérifier rendu mode.

Meta balises: useSeoMeta() et useHead()

Nuxt’s head management runs on Unhead, and it donne vous two composables pour différent jobs.

useSeoMeta() est le un à reach pour pour le SEO et social meta balises. c’est a flat, type-sûr API avec typed parameters. Preuve à l’appui de cette affirmation useSeoMeta is a typed Nuxt API for SEO and social meta tags. Portée : Current Nuxt composable. Niveau de confiance : élevé · Vérifié : Nuxt: useSeoMeta Il aide éviter le classic Ouvrir Graph bug de en utilisant name où vous nécessaire property:

useSeoMeta({
  title: 'My Page Title',
  ogTitle: 'My Page Title',
  description: 'Concise page-specific description with the key information first',
  ogDescription: 'Concise social description tailored to this page',
  ogImage: 'https://mysite.com/og-image.png', // must be an absolute URL
  twitterCard: 'summary_large_image',
})

useHead() est le general-purpose head outil pour tout sinon — scripts, lien balises, corps attributs, et titre templates:

useHead({
  titleTemplate: '%s · My Site Name',
  htmlAttrs: { lang: 'en' },
})

Le fiable layering modèle est: static defaults (charset, viewport, favicon) dans nuxt.config.ts → site-wide titre template et mondial OG defaults dans app.vue → page-spécifique overrides via useSeoMeta() dans lune page component. A courant bug est putting useSeoMeta() dans a layout au lieu de lune page, qui overwrites spécifique page balises avec générique ones. Et since moteur de recherches lire le initial charger, SEO meta généralement ne fait pas besoin à être reactive — useServerHead() skips le client-side re-execution.

Qui API, and ce que it en réalité proves:

APIScopeReactive?Ce que il proves à propos de sortie
useSeoMeta()Flat, typed SEO/social meta seulementOui (par défaut)Sets typed properties correctement — pas que le route est unique, canonical, or indexable; vous encore propre que logic
useHead()N’importe quoi dans <head> — scripts, liens, attrs, titre templateOui (par défaut)General head contrôler; même caveat — API utiliser n’est pas proof de a correct serveur réponse
useServerHead() / serveur-seulement callsMême as ci-dessusAucun — serveur seulement, skips client re-executionConfirms le balise ships une fois dans serveur HTML; ne fait pas confirmer client navigation re-sets il si vous rely on il là

Appel un de ces composables indique vous le API ran — il ne fait pas par itself tell vous ce que a direct serveur réponse or a client-side route modifier en réalité emits. Confirmer avec View Source or curl, pas simplement “Je called useSeoMeta().”

Le @nuxtjs/seo module ecosystem (Harlan Wilton) — optional, pas core

Nuxt core ne fait pas ship a sitemap, a robots.txt, OG image generation, or Schema.org out de le box — ceux sont à l’extérieur Nuxt’s propre primitives (useHead, useSeoMeta, route règles, rendu modes). Le community fills que gap avec Harlan Wilton’s @nuxtjs/seo — a séparément-installed, tiers umbrella package (nuxtseo.com, currently à v5.x, actively maintained, targeting Nuxt 3,16+ et Nuxt 4) que bundles six modules. Installing il donne vous sitemap, robots, OG-image, et schema generation — il ne fait pas par itself guarantee le sortie est correct pour votre routes; vérifier ce que il produces le même façon vous’d vérifier n’importe quoi sinon:

ModuleCe que il fait
@nuxtjs/robotsrobots.txt + meta robots + X-Robots-Tag headers
@nuxtjs/sitemapAuto XML sitemaps depuis pages + dynamic routes
nuxt-og-imageDynamic OG images (a Vue template → an image)
nuxt-schema-orgSchema.org JSON-LD données structurées
nuxt-seo-utilsURL canoniques, breadcrumbs, defaults
nuxt-link-checkerConstruire-time broken-lien detection

Install le entier bundle avec npx nuxt module add seo, or grab individual modules (npx nuxt module add sitemap robots). A quelques behaviors worth knowing:

«- @nuxtjs/sitemap auto-generates from your pages/ directory plus dynamic routes, splits into a sitemap index automatically past 50,000 URLs, supports i18n multi-language sitemaps, and has built-in IndexNow support. One thing to get right: Google ignores changefreq and priority; only an accurate lastmod matters, and only when content genuinely changes. » (Traduction) (Résumé en français de la section soixante, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- @nuxtjs/robots generates robots.txt, the robots meta tag, and the X-Robots-Tag header — and by default it disallows all crawlers on non-production environments, which is exactly the staging-indexation footgun that bites headless builds. It also gives you per-bot rules, so you can block GPTBot specifically while leaving everyone else alone (be intentional — block an AI crawler and it won’t cite you). » (Traduction) (Résumé en français de la section soixante, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- nuxt-seo-utils handles canonical URLs and, usefully, strips tracking parameters (utm_*, fbclid, gclid) from canonicals automatically. » (Traduction) (Résumé en français de la section soixante, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.)

nuxt/image et Core Web Vitals

@nuxt/image est le image module: automatic responsive srcset, modern formats (WebP/AVIF), built-dans optimization via CDN providers, et lazy chargement. Deux règles carry la plupart de le SEO valeur:

  • Jamais lazy-charger le LCP image. Votre hero image devrait charger eagerly; lazy-loading il delays votre Plus grand affichage de contenu.
  • Toujours définir width et height donc le navigateur reserves space et vous ne pas prendre a Décalage cumulatif de mise en page hit.
<NuxtImg
  src="/hero.jpg"
  width="1200"
  height="630"
  alt="Descriptive alt text"
  :loading="isHeroImage ? 'eager' : 'lazy'"
  format="webp"
/>

Le 2026 targets à aim pour (p75): LCP ≤ 2,5s, INP ≤ 200ms, CLS ≤ 0,1. On Nuxt apps, INP est le un que tends à suffer parce que hydration crée entrée lag — qui est exactly ce que Nuxt Islands et <NuxtIsland> sont pour.

Nuxt Content + SEO

Si vous êtes en utilisant @nuxt/content (le markdown/MDX contenu module), le integration avec @nuxtjs/seo est straightforward mais a un ordering gotcha: charger @nuxtjs/seo avant @nuxt/content dans votre modules array. Vous pouvez alors définir SEO dans contenu frontmatter (title, description, robots, ogImage, schemaOrg) et pull il dans votre [slug].vue template avec useSeoMeta() après fetching le contenu. Ce est le Nuxt-native version de le headless-CMS modèle, et le même “rebuild ce que le plugin a fait” discipline s’applique.

Courant Nuxt SEO mistakes

«1. Using SPA mode (ssr: false) for content you want indexed. The most expensive mistake — and the one that makes you invisible to AI crawlers. 2. Relative URLs for OG images. ogImage must be an absolute URL or social previews break. 3. useSeoMeta() in a layout instead of the page — generic tags overwrite page-specific ones. 4. Not verifying rendered HTML — View Source ≠ DevTools ≠ what Google rendered. Use URL Inspection. 5. Blocking JS/CSS in robots.txt — Google won’t render from blocked files. 6. Leaving the staging noindex/disallow in place after launch (or, conversely, forgetting @nuxtjs/robots blocks non-prod by default and wondering why prod is fine but a custom env isn’t). 7. Lazy-loading the LCP image — tanks your LCP. 8. Missing width/height on images — CLS. 9. changefreq/priority in sitemaps — Google ignores them; only lastmod counts. 10. Reaching for dynamic rendering. Google deprecated it — “dynamic rendering is a workaround and not a long-term solution” — and it only serves the engines you configure it for, missing Bing and every AI crawler. With Nuxt you never need it: SSR and SSG already give crawlers complete HTML. » (Traduction) (Résumé en français de la section soixante-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

llms.txt and AEO

llms.txt est a plain-texte fichier — robots.txt’s cousin — que aide AI outils navigate votre contenu. Le nuxt-llms module auto-generates /llms.txt et /llms-full.txt depuis Nuxt Contenu. As de late 2025 son principal consumers sont MCP serveurs et AI coding outils (Cursor, Claude Code) plutôt que ChatGPT or Perplexity directement, et c’est la plupart utile pour documentation sites et technique blogs — moins donc pour e-commerce or news. Worth ajout si vous êtes a docs/dev site; pas a priority sinon.

Où ce fits

Nuxt SEO est vraiment a concrete application de JavaScript SEO via Nuxt’s propre conventions — et il overlaps heavily avec le SEO pour a CMS headless topic quand votre Nuxt frontend pulls depuis a headless backend. Le principles ne pas modifier; Nuxt simplement donne vous bon defaults et a strong module ecosystem à implement les avec.

Ajouter une note d’expert

Épingler une citation d’expert

Nouvelle personne ? Créez son profil non revendiqué à /admin/experts/ → Épingler une citation d’expert d’abord.