Nuxt 3 SEO & Meta Management
Nuxt 3 renders universally by default, which means it already does the hardest part of JavaScript SEO — putting content and metadata in the HTTP response — without extra configuration. The work that remains is choosing the right rendering mode per route and setting metadata cleanly per page. This guide maps Nuxt’s SEO surface and sits within framework-specific SEO implementations, applying the rendering-strategy decisions in Nuxt’s idiom.
Prerequisites
- Nuxt 3 with the default universal (SSR) rendering, or Nitro configured for your hosting target.
- A clear per-route rendering intent (SSR, prerender/SSG, or ISR).
- Page components using
useSeoMeta/useHead, ordefinePageMetafor route-level config. - Search Console access to verify rendered metadata.
How it breaks
The typical Nuxt SEO regression is disabling SSR globally (ssr: false) to fix a build issue, turning the whole app into a client-rendered SPA — so every route reverts to the empty-shell failure Nuxt was protecting you from. A subtler one is setting metadata in onMounted, which runs only on the client and never makes it into the server response.
Step-by-step fix
-
Keep SSR on; set the mode per route with route rules.
// nuxt.config.ts export default defineNuxtConfig({ routeRules: { '/': { prerender: true }, // SSG '/blog/**': { isr: 3600 }, // ISR '/shop/**': { ssr: true }, // SSR }, }); -
Set standard metadata with
useSeoMeta. It is typed and runs during SSR.<script setup> const { data: post } = await useFetch(`/api/posts/${useRoute().params.slug}`); useSeoMeta({ title: () => post.value.title, description: () => post.value.summary, ogTitle: () => post.value.title, ogImage: () => post.value.ogImage, }); </script> -
Add structured data with
useHead. Use it for JSON-LD and link tags — detailed in dynamic meta tags with useHead in Nuxt 3. -
Never set SEO metadata in
onMounted— it runs client-only and misses the server response.
Gotchas & edge cases
- Global
ssr: false. Turns the app into a CSR SPA; scope client-only rendering to route rules instead. awaitbeforeuseSeoMeta. Ensure data is awaited so the title is resolved during SSR, not after.- Duplicate tags from manual
useHead. PreferuseSeoMetafor standard tags to avoid conflicting entries. - Canonical on parameterized routes. Set a clean canonical via
useHeadfor filtered or paginated routes — see canonical URL management.
Validation checklist
Performance & crawl-budget notes
Because Nuxt renders metadata during SSR, routes index in the first wave and skip the render queue, preserving crawl budget. Route rules let you reserve full SSR for genuinely dynamic routes and prerender the rest, minimizing server cost while keeping everything crawlable.
Go deeper
- Dynamic meta tags with useHead in Nuxt 3 — data-driven titles, social tags, and JSON-LD.
Frequently Asked Questions
Is Nuxt 3 good for SEO by default? Yes. Nuxt 3 renders universally by default, so routes ship server-rendered HTML with metadata in the response. The SEO work is mostly choosing the right per-route rendering mode with route rules and setting per-page metadata with useSeoMeta or useHead.
Should I use useHead or useSeoMeta in Nuxt 3? Use useSeoMeta for standard SEO and social tags — it is typed and maps directly to title, description, and og: properties. Use useHead for anything useSeoMeta does not cover, such as link tags, scripts, or JSON-LD structured data.
Related
- Vue Router Dynamic Meta Tags Setup — the underlying Vue patterns Nuxt builds on.
- CSR, SSG, SSR & ISR Rendering Strategies — the modes Nuxt route rules express.
- JSON-LD Implementation in Single Page Apps — structured data patterns to use with useHead.
← Back to Framework-Specific SEO Implementations