Nuxt SEO: useSeoMeta, the SEO modules, and the client-rendering trap

You use Nuxt because it renders on the server. Keep that advantage. This guide shows what to set with useSeoMeta and useHead, how to use the Nuxt SEO modules for sitemap, robots, schema and social images, and how to avoid the client-rendering trap that hides content from Google.

By , founder of Porteur · Updated 14 September 2026 · Markdown

What a healthy Nuxt page looks like to Google

Server-side rendering is the default in Nuxt. Keep it. A healthy page serves HTML with the main content, title, meta description and links in the first response. JSON-LD for schema sits in the head. Images have size attributes. Canonicals are correct. The sitemap lists the page. Robots allows it.

  • View source shows the article text for "/guides/getting-started" without running JavaScript.
  • The head contains one title and one meta description, set with useSeoMeta.
  • There is a canonical link to the clean URL, for example https://yourproduct.com/guides/getting-started.
  • JSON-LD for the page type is present, for example Article or Product.
  • Largest image on the page has width and height attributes so it does not shift layout.
  • The page is listed in the sitemap, and robots.txt does not block it.

The client-rendering trap in Nuxt

Nuxt renders on the server by default, but you can break it. If you fetch the content only on the client, Google may see an empty shell in the raw HTML.

  • Fetching data in onMounted or only in client-only composables means no content at render time.
  • Setting useFetch or $fetch to run only on the client hides content from the first response.
  • Client-only components for core content do not render on the server.
  • Switching to a client-only layout for speed, then forgetting to bring back SSR for content pages.
  1. Put content fetching on the server

    Fetch page content in a server context so it renders on first load. In Nuxt, avoid client-only data loads for the main content.

  2. Check "View source"

    Open your page, then view source. If the main text on "/pricing" is missing here, it is not server-rendered.

  3. Use URL Inspection

    In Search Console, run Test live URL on the page. Compare the HTML Google sees to your expectation. Fix anything that only appears after interaction.

useSeoMeta vs useHead, and where to set them

useSeoMeta is for common SEO fields. useHead is for any other head element. Use useSeoMeta for title and descriptions, and useHead for link tags and custom meta.

script setup
// pages/guides/getting-started.vue
const title = 'Getting started with YourProduct'
const description = 'Install, configure and ship your first workflow.'

useSeoMeta({
  title,
  description,
  ogTitle: title,
  ogDescription: description,
  twitterTitle: title,
  twitterDescription: description
})

useHead({
  link: [
    { rel: 'canonical', href: 'https://yourproduct.com/guides/getting-started' }
  ]
})
  • Set base defaults in app.vue or a layout, for example site name in the title template.
  • Set page-specific title and description in the page component.
  • Put the canonical where the final URL is known, often in the page.
  • Do not set duplicate titles in multiple places. One source of truth per field.

Check the output in head. If you see two titles or two descriptions, remove one. A fixed page has one clear title under about 60 characters, one description that reads well, and one canonical to the clean URL.

The Nuxt SEO module set: sitemap, robots, schema.org, social images

Use the official Nuxt SEO module set for the plumbing. It covers the sitemap, robots, schema.org and social images. Each module is built to generate its piece so you do not hand-code it on every page.

  • Sitemap: expose your routes and keep last modified dates in sync. Include only indexable URLs.
  • Robots: ship a robots.txt that allows your pages and blocks staging or private routes.
  • Schema.org: add JSON-LD for common types like Organization, Product and Article.
  • Social image: generate or set og:image and twitter:image so shares look right.

Set module config in nuxt.config according to the docs as of 2026. For dynamic sites, check the module’s route discovery. If it misses custom paths, feed it routes programmatically. If the module supports i18n alternates, enable it when you have multiple languages. When versions differ, check the platform's current settings and examples in the module readme.

Sitemap and Search Console: wire them and verify

When the sitemap is live, submit it in Search Console. This helps Google discover new and changed URLs faster. It also gives you a simple place to check status.

  1. Open Search Console and add your property

    Verify your domain if you have not already. Use DNS verification so subdomains and paths are covered.

  2. Submit the sitemap index URL

    Use your module’s sitemap path, for example https://yourproduct.com/sitemap.xml or a sitemap index. Wait for processing.

  3. Fix errors the report flags

    Remove 404s from the sitemap, and do not include URLs with noindex. Make sure canonical URLs resolve with 200.

On a fixed site the Sitemaps report shows all submitted sitemaps as Success, with most URLs discovered. Your important pages, like "/pricing" and "/guides/getting-started", appear as Indexed in Coverage and receive impressions over time.

Robots rules and safe staging

Keep robots.txt simple. Allow what should be indexed. Block staging and private paths. Let static assets be crawled so pages can render correctly.

# /robots.txt for production
User-agent: *
Allow: /
Sitemap: https://yourproduct.com/sitemap.xml
# /robots.txt for staging
User-agent: *
Disallow: /

Set robots via the Nuxt robots module. For password-protected staging, keep it blocked by authentication too. Never rely on robots alone to hide private content. Before launch, switch to the production rules and remove any noindex meta from pages that should rank.

Schema.org with JSON-LD: what to add and how to test

Use the schema.org module in the Nuxt SEO set to add JSON-LD. Start with Organization sitewide. On your homepage, include your brand, logo and URL. On product or feature pages, describe the product. On blog posts, include Article. For software, you can model the page as a SoftwareApplication when that fits the intent.

script setup
// Example: add Organization JSON-LD in app.vue or a layout
useHead({
  script: [
    {
      type: 'application/ld+json',
      children: JSON.stringify({
        '@context': 'https://schema.org',
        '@type': 'Organization',
        name: 'YourProduct',
        url: 'https://yourproduct.com'
      })
    }
  ]
})
  • Keep one clear JSON-LD block per entity you describe.
  • Match visible content. Do not claim offers or reviews that are not shown.
  • Test pages in the Rich Results Test to check parsing and eligibility.

On a fixed page the JSON-LD validates, and the test shows the detected types. If a rich result is supported for your type, you see eligibility. If not, you still help search understand the page.

Images: nuxt/image for page speed and social shares

Use nuxt/image to optimise images. It handles formats and sizing so the Largest Contentful Paint can be fast. Zero JavaScript is not the goal here, but less client work helps performance and crawlability.

  • Mark the main image on the page without lazy loading when it is the hero.
  • Always set width and height on images to prevent layout shift.
  • Serve appropriately sized images for each slot. Avoid shipping giant assets into small containers.
  • Set alt text that describes the image briefly. Keep it relevant to the page.

For social sharing, set og:image and twitter:image. The Nuxt SEO module set can generate images or accept a static URL. Use a consistent template so shares of "/blog/how-we-built-search" show a clear title and brand. Test in a social preview tool before you publish.

Proving server rendering with URL Inspection

Do not guess. Test pages with the URL Inspection tool in Search Console. You will see what Google last crawled and what it gets from a live fetch. That confirms your server rendering and meta output.

  1. Inspect the URL

    Paste the full URL. Look at Coverage to confirm it is Indexed. If not, read the reason.

  2. Test live URL

    Open the live test. View crawled page HTML. Your main text should be visible here. Confirm title, description and canonical.

  3. Request indexing after fixes

    If you fixed rendering or meta issues, request indexing. Then watch for changes in the page’s impressions.

A fixed page shows server-rendered content in the live HTML. The canonical points to itself. No client-only placeholders remain. The page moves from Discovered or Crawled, currently not indexed to Indexed within a normal crawl cycle.

Core Web Vitals for Nuxt pages

Your build and hosting choices affect Core Web Vitals. The goals as of 2026 are: LCP up to 2.5 s, CLS up to 0.1, INP up to 200 ms. Nuxt helps with server rendering. You still need to ship light pages and stable layouts.

  • Set explicit sizes on images and embeds to control layout shift.
  • Keep client JavaScript lean. Remove unused UI libraries on content pages.
  • Defer non-essential third-party scripts. Test their cost in lab and field.
  • Make the LCP element simple: a text block or an optimised image via nuxt/image.
  • Watch INP. Heavy event handlers and long tasks penalise responsiveness.

Use PageSpeed Insights. It shows field data when there is enough traffic and a Lighthouse run for lab data. Expect some variance between runs. Aim to fix clear regressions rather than chasing a single score point. On a fixed page the field data trends to Good over a 28 day window.

Questions

Sources

Check my site, free

Paste a key Nuxt URL into the free check to see if your HTML renders server-side, your meta and schema ship correctly, and which rivals already rank on those searches.

  • Free check, no card
  • Read-only, your own accounts
  • Readable by your agent

Read next