💚

GEO con Nuxt.js: Guía completa de implementación

intermediate

Nuxt.js implementa GEO con el composable useSeoMeta para meta tags y Open Graph, useHead para JSON-LD y URL canónica, y SSR activado (default). El composable useSeoMeta tipado previene errores comunes en property names. Nuxt genera HTML en el servidor, compatible natiamente con crawlers de IA.

GEO con Nuxt.js: Guía completa de implementación

Nuxt.js implementa GEO con el composable useSeoMeta para meta tags y Open Graph, useHead para JSON-LD y URL canónica, y SSR activado (default). El composable useSeoMeta tipado previene errores comunes en property names. Nuxt genera HTML en el servidor, compatible nativamente con crawlers de IA.

Implementación de página

<!-- pages/guia-geo.vue -->
<script setup lang="ts">
const publishedTime = '2026-04-18T00:00:00Z'
const url = 'https://misitio.com/guia-geo'
const description = 'GEO en Nuxt.js con useSeoMeta, Open Graph completo y JSON-LD. Guía con ejemplos.'

useSeoMeta({
  title: 'Cómo implementar GEO en Nuxt.js | Mi Sitio',
  description,
  ogType: 'article',
  ogTitle: 'Cómo implementar GEO en Nuxt.js',
  ogDescription: description,
  ogUrl: url,
  ogSiteName: 'Mi Sitio',
  ogImage: 'https://misitio.com/og/guia-geo.jpg',
  ogLocale: 'es_ES',
  articlePublishedTime: publishedTime,
  articleModifiedTime: publishedTime,
  articleAuthor: 'https://misitio.com/author/mi-empresa',
  articleSection: 'Guías técnicas',
  articleTag: ['GEO', 'Nuxt.js'],
  robots: 'index, follow',
})

useHead({
  link: [{ rel: 'canonical', href: url }],
  script: [{
    type: 'application/ld+json',
    innerHTML: JSON.stringify({
      '@context': 'https://schema.org',
      '@type': 'Article',
      headline: 'Cómo implementar GEO en Nuxt.js',
      description,
      author: { '@type': 'Organization', name: 'Mi Empresa' },
      publisher: {
        '@type': 'Organization',
        name: 'Mi Sitio',
        logo: { '@type': 'ImageObject', url: 'https://misitio.com/logo.png' },
      },
      datePublished: publishedTime,
      dateModified: publishedTime,
      mainEntityOfPage: { '@type': 'WebPage', '@id': url },
    }),
  }],
})
</script>

<template>
  <main>
    <article>
      <h1>Cómo implementar GEO en Nuxt.js</h1>
      <p>GEO en Nuxt.js usa useSeoMeta para meta tags tipados y useHead para JSON-LD.</p>
    </article>
  </main>
</template>

Requisito: ssr: true en nuxt.config.ts (es el default). Sin SSR los crawlers de IA ven HTML vacío.

Metadata dinámica para páginas de contenido

Para posts de blog u otras páginas dinámicas, obtén los datos antes de configurar SEO:

<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const { data: post } = await useAsyncData(
  `post-${route.params.slug}`,
  () => $fetch(`/api/posts/${route.params.slug}`)
)

if (post.value) {
  useSeoMeta({
    title: `${post.value.title} | Mi Sitio`,
    description: post.value.excerpt,
    ogType: 'article',
    ogTitle: post.value.title,
    ogDescription: post.value.excerpt,
    ogUrl: `https://misitio.com/blog/${route.params.slug}`,
    articlePublishedTime: post.value.publishedAt,
    articleModifiedTime: post.value.updatedAt,
    articleSection: post.value.category,
    articleTag: post.value.tags,
  })

  useHead({
    link: [{ rel: 'canonical', href: `https://misitio.com/blog/${route.params.slug}` }],
    script: [{
      type: 'application/ld+json',
      innerHTML: JSON.stringify({
        '@context': 'https://schema.org',
        '@type': 'Article',
        headline: post.value.title,
        description: post.value.excerpt,
        datePublished: post.value.publishedAt,
        dateModified: post.value.updatedAt,
        author: { '@type': 'Person', name: post.value.author.name },
        publisher: { '@type': 'Organization', name: 'Mi Sitio' },
      }),
    }],
  })
}
</script>

Defaults globales en nuxt.config.ts

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      htmlAttrs: { lang: 'es' },
      meta: [
        { name: 'robots', content: 'index, follow' },
      ],
    },
  },
  
  // SSR activo (default, pero explícito por claridad)
  ssr: true,
  
  // Sitemap automático
  modules: ['@nuxtjs/sitemap'],
  sitemap: {
    // Genera sitemap con lastmod automático
  },
})

robots.txt en Nuxt

Crea public/robots.txt:

User-agent: GPTBot
Allow: /

User-agent: OAI-SearchBot
Allow: /

User-agent: ClaudeBot
Allow: /

User-agent: Claude-User
Allow: /

User-agent: Claude-SearchBot
Allow: /

User-agent: PerplexityBot
Allow: /

User-agent: Google-Extended
Allow: /

User-agent: BingBot
Allow: /

User-agent: *
Allow: /

Sitemap: https://misitio.com/sitemap.xml
Sitemap: https://misitio.com/llms.txt

llms.txt en Nuxt

Crea public/llms.txt:

# Mi Sitio
> Descripción de una línea de qué hace el sitio y a quién sirve.

## Contenido principal
- [Guía GEO](https://misitio.com/guia-geo): Guía completa de Generative Engine Optimization
- [Blog técnico](https://misitio.com/blog): Artículos sobre desarrollo web y GEO

## Sobre nosotros
- [Quiénes somos](https://misitio.com/about): Equipo y credenciales

Checklist GEO para Nuxt.js

  • SSR activo en nuxt.config.ts (ssr: true)
  • useSeoMeta: title, description, ogType=article, ogTitle, ogDescription, ogUrl, ogImage, ogLocale
  • useSeoMeta: articlePublishedTime y articleModifiedTime
  • useHead: canonical URL
  • useHead: JSON-LD Article schema con publisher y fechas
  • public/robots.txt con los 8 crawlers de IA permitidos
  • public/llms.txt con descripción del sitio y páginas principales
  • Sitemap con lastmod (módulo @nuxtjs/sitemap recomendado)
  • Estructura de contenido en pirámide invertida
  • Core Web Vitals: LCP < 2.5s, INP < 200ms, CLS < 0.1