SEO de Nuxt

Nuxt ofrece renderizado del lado del servidor por defecto, pero eso es una configuración por ruta, no una garantía: HTML completo para los rastreadores solo en las rutas que lo mantienen. Modos de renderizado, useSeoMeta(), el kit de herramientas @nuxtjs/seo, advertencias de hidratación y Nitro, Core Web Vitals y los errores que te cuestan silenciosamente.

Publicado por primera vez: 26 jun 2026 · Última actualización: 22 ago 2026 · Avanzado
Idiomas
1 señal de evidencia en esta página

Nuxt renderiza páginas en el servidor por defecto, por lo que una ruta que mantiene ese valor predeterminado da a los rastreadores un documento HTML completo en lugar del caparazón vacío que envía una SPA de Vue simple, pero es una configuración por ruta: routeRules o un ssr:false global pueden cambiar cualquier ruta a CSR, así que verifica la ruta real en lugar de asumir por el nombre del framework. La decisión fundamental es el modo de renderizado por ruta: SSR (predeterminado), SSG mediante nuxt generate o reglas de ruta híbridas, porque las metaetiquetas, el esquema y los sitemaps vienen después. Usa useSeoMeta() para meta, trata el paquete @nuxtjs/seo de Harlan Wilton como un kit de herramientas de terceros opcional (no núcleo de Nuxt) para robots/sitemap/OG/schema/canonical, nunca recurras al renderizado dinámico (Google lo ha desaprobado), verifica la hidratación/payload y el comportamiento de caché/preset de despliegue de Nitro independientemente del HTML del servidor, y recuerda que los contratos de renderizado de los rastreadores de IA varían según el proveedor: SSR/SSG pone el contenido en HTML crudo y maximiza la cobertura.

TL;DR — El valor predeterminado de Nuxt es el renderizado en el servidor, por lo que una ruta que mantiene ese valor predeterminado obtiene un DOM completo en lugar del caparazón vacío que envía una SPA de Vue simple — pero eso es un resultado por ruta: ssr: false o una anulación de routeRules pueden convertir cualquier ruta en CSR o híbrida, así que prueba la ruta real, no el nombre del proyecto. La estrategia de renderizado es la decisión fundamental — SSR (predeterminado), SSG (nuxt generate) o routeRules híbridos — porque los metadatos, el esquema y los sitemaps vienen después. Usa useSeoMeta() para las etiquetas meta (useHead() para el resto del head, variantes solo de servidor cuando no necesitas reactividad), y trata el paquete @nuxtjs/seo de Harlan Wilton como un kit de herramientas de terceros opcional para robots/sitemap/OG/schema/canonical — no es parte del núcleo de Nuxt, y no es prueba de que su salida sea correcta hasta que lo verifiques. Nunca uses renderizado dinámico (Google lo ha desaprobado). El renderizado de los rastreadores de IA varía según el proveedor — SSR/SSG maximiza la cobertura de HTML crudo. Más allá del HTML inicial, verifica la hidratación/payload, los ajustes preestablecidos de implementación de Nitro y el almacenamiento en caché, y el estado HTTP directo de forma independiente — el HTML del servidor por sí solo no prueba nada de eso. Las reglas habituales de SEO para JavaScript siguen aplicándose: enlaces reales <a href>, no bloquees JS/CSS, observa el HTML renderizado frente al HTML crudo.

Nuxt es la respuesta de Vue al problema de las SPA

Vue, por sí solo, envía una aplicación de una sola página: un caparazón HTML más JavaScript que construye el DOM en el navegador. Nuxt es el meta-framework sobre Vue (que se ejecuta en el motor de servidor Nitro en Nuxt 3, con Nuxt 4 siguiendo en 2025), y toda su razón de existir — desde el punto de vista del SEO — es que renderiza en el servidor por defecto. Cada página llega como un documento HTML completamente formado, que es exactamente lo que Googlebot quiere leer sin tener que ejecutar JavaScript primero. El SEO de Vue simple es un tema propio con sus propios modos de fallo; aquí asumo que has elegido Nuxt precisamente para no tener que luchar contra el problema de las SPA.

Este es el mismo punto que hago sobre JavaScript en general: “fine for search engines” (traducción) «adecuado para los motores de búsqueda»; allí incluyo expresamente a Gatsby, Next y Nuxt. Los valores predeterminados de Nuxt apuntan en la dirección correcta. La mayoría de los problemas de SEO de Nuxt son personas que desactivan esos valores predeterminados o apilan errores sobre ellos.

La estrategia de renderizado es la base — se decide por ruta, no por proyecto

Antes de las etiquetas meta, antes del esquema, antes de los sitemaps, la pregunta que decide todo es ¿cómo se produce el HTML para esta ruta específica? Nuxt documenta el renderizado universal (en el servidor) como el valor predeterminado de toda la aplicación, pero ese valor predeterminado no es una garantía a nivel de ruta: un ssr: false global cambia toda la aplicación al renderizado en el cliente, y routeRules puede asignar un modo diferente a cualquier patrón de URL. “Esto es una aplicación Nuxt” no te dice nada sobre cómo se renderiza una página en particular — tienes que comprobar la ruta. Nuxt te da cinco estrategias:

ModoCómo se configuraImpacto en SEOMejor para
Universal / SSRPredeterminado (ssr: true)Excelente — HTML completo en cada solicitudContenido dinámico y personalizado
Estático / SSGnuxt generateExcelente — HTML construido en el momento de la implementaciónBlogs, documentación, marketing
HíbridorouteRules por rutaExcelente — mezcla por rutaSitios grandes con contenido mixto
SPA / CSRssr: falsePobre para contenido indexadoPaneles de control, paneles de administración
En el bordeObjetivo de implementaciónExcelente — TTFB bajoRendimiento global

La documentación oficial de Nuxt es contundente sobre por qué la renderización del lado del cliente es la elección incorrecta para el contenido: “takes more time” (traducción) «lleva más tiempo», mientras que con la renderización del servidor los “web crawlers can directly index” (traducción) «rastreadores web pueden indexar directamente» el contenido de la página. Evidence for this claim Nuxt documents that universal rendering delivers HTML content immediately and allows crawlers to index it directly. Scope: Nuxt rendering; no indexing guarantee. Confidence: high · Verified: Nuxt: Rendering modes (Documentación de renderizado de Nuxt.) CSR (ssr: false) está pensado para back-office, paneles y juegos, no para nada que quieras indexar.

La renderización híbrida es la jugada maestra para sitios grandes. Las reglas de ruta en nuxt.config.ts te permiten configurar el modo de renderizado y caché por patrón de URL:

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-while-revalidate) e isr (regeneración estática incremental) generan una página estáticamente y luego la actualizan en segundo plano: ideal para comercio electrónico con muchas páginas o noticias donde una reconstrucción completa en cada cambio no es práctica. Nuxt Islands (<NuxtIsland>) renderizan componentes sin enviar JavaScript del lado del cliente, reduciendo el costo de hidratación y ayudando al INP, la Core Web Vital que suele ser el problema más común en aplicaciones Nuxt.

Cómo verificar lo que realmente enviaste: Ver código fuente muestra el HTML sin procesar que el servidor envió; si tu contenido está ahí, estás renderizando en el servidor. El panel Elements de DevTools muestra el DOM renderizado. Y la herramienta URL Inspection de GSC muestra lo que Google realmente obtuvo y renderizó: la fuente de la verdad. No confíes en “se ve bien en mi navegador”.

Cómo maneja Googlebot una aplicación Nuxt

Google procesa cualquier aplicación JavaScript en tres fases: rastreo, renderizado e indexación, y el problema es el tiempo: el renderizado ocurre en una cola, no al instante. Como lo expresé en mi guía de SEO para JavaScript, el renderizador es paciente: “there is no fixed timeout for the renderer… It’s really patient, and you should not be concerned.” (traducción) «No hay un tiempo de espera fijo para el renderizador… Es realmente paciente, y no deberías preocuparte.» Pero paciente no es lo mismo que rápido para contenido fresco. Si envías una página renderizada en el cliente, tu contenido no existe para Google hasta que esa ola de renderizado se ejecute; SSR y SSG cierran esa brecha porque el HTML está completo en la primera solicitud.

Dos cosas más importan a escala. Renderizar JavaScript es costoso: de mi charla JavaScript SEO (Ungagged) de 2019, los costos de rastreo aumentan aproximadamente 20× una vez que Google tiene que renderizar (direccional, pero el orden de magnitud sigue siendo válido). Y Google toma la directiva más restrictiva entre el HTML sin procesar y el renderizado, por lo que un noindex inyectado por JavaScript ganará sobre un index en el HTML sin procesar, y viceversa. Un canonical inyectado mediante JavaScript se respeta solo si no hay un canonical en el HTML sin procesar ya. Mantén tus señales de robots y canonical en el HTML renderizado en el servidor, lo cual Nuxt hace por ti cuando SSR está activado.

La realidad de los rastreadores de IA

Este es el detalle de 2026. Los rastreadores de IA (GPTBot, ClaudeBot, PerplexityBot y los demás) generalmente no ejecutan JavaScript en absoluto. Indexan el HTML sin procesar y nada más. Por lo tanto, una página Nuxt renderizada en el cliente es efectivamente invisible para los motores de respuesta de IA. SSR o SSG no solo es mejor para Google aquí; es el precio de entrada para la optimización de motores de respuesta también. Si quieres que tu contenido sea citado por ChatGPT, Perplexity o Claude, tiene que estar en el HTML en la primera solicitud.

Más allá del HTML inicial: payload, hidratación y códigos de estado

Obtener HTML del servidor con tu contenido es necesario pero no suficiente: varias cosas pueden salir mal después de esa primera respuesta, y “revisé Ver código fuente” no las cubre:

  • Carga útil e hidratación. El renderizado universal envía el HTML y una carga útil de datos serializada que el cliente usa para hidratar — adjuntar los listeners de eventos y continuar donde el servidor lo dejó — sin volver a buscar. Que el HTML del servidor se vea bien no prueba que la hidratación haya tenido éxito, que la navegación del cliente reproduzca el mismo contenido, o que la carga útil no esté desactualizada. Si una página se siente bien en la primera carga pero se rompe después de un cambio de ruta en el cliente, eso es un problema de hidratación/carga útil, no un problema del modo de renderizado.
  • <ClientOnly> y contenido solo para el navegador. Envolver algo en <ClientOnly> — común para widgets que dependen de APIs del navegador — significa que está ausente de la respuesta del servidor incluso en una ruta por lo demás universal. Si tu contenido principal, un enlace clave o tus meta etiquetas terminan dentro de un límite solo para el cliente, los rastreadores y los bots de IA que solo leen el HTML crudo lo pasan por alto, independientemente de tu configuración del modo de renderizado. Inspecciona la respuesta real, no solo la configuración del modo de renderizado.
  • Los códigos de estado y las redirecciones no se autoverifican. Una página de error de Nuxt que se renderiza en el navegador, o una redirección impulsada por navigateTo()/composable, no prueba por sí misma qué estado HTTP envió la respuesta directa del servidor. La guía de Google es explícita en que los códigos de estado significativos importan para el rastreo y la indexación — confirma el encabezado real con curl -I, no lo que muestra la página de error renderizada en el cliente.

Nada de esto es un argumento en contra del renderizado universal — es el recordatorio de que “el HTML está renderizado en el servidor” es la primera comprobación, no la última.

Nitro, presets de despliegue y límites de caché

La salida del servidor de Nuxt se construye con Nitro, y Nitro compila de manera diferente dependiendo del preset de despliegue que tengas como objetivo (servidor Node, Cloudflare, Vercel, Netlify, estático y otros). Eso importa para el SEO porque los presets y adaptadores pueden diferir en las APIs de runtime disponibles, el comportamiento de caché, el soporte de streaming, el despliegue regional y el acceso al sistema de archivos — una regla de ruta o un handler de servidor que funciona bajo un preset no está garantizado que se comporte de manera idéntica bajo otro. Dos consecuencias que vale la pena probar explícitamente en lugar de asumir:

  • Las claves de caché y la invalidación son específicas de la ruta, no automáticas. Las reglas de ruta swr e isr cachean y regeneran la salida, pero una clave de caché incorrecta, una invalidación faltante o un encabezado de caché establecido por tu plataforma de despliegue pueden servir HTML obsoleto, personalizado o inconsistente a los rastreadores. Comprueba la antigüedad real de la respuesta y cualquier encabezado Cache-Control/Age en una URL en vivo, no solo la configuración de routeRules.
  • La paridad de producción no está garantizada por el comportamiento de staging. Una ruta que se renderiza correctamente en el desarrollo local o en un despliegue de vista previa no confirma que el preset de producción produzca la misma salida — las rutas del servidor, las redirecciones y el manejo de errores viven en la capa de servidor de Nitro, y esa capa es la parte que más probablemente difiera según el objetivo. Prueba la URL de producción directamente después de cualquier cambio de despliegue, de la misma manera que verificarías el modo de renderizado.

Meta etiquetas: useSeoMeta() y useHead()

La gestión de head de Nuxt se ejecuta en Unhead, y te ofrece dos composables para diferentes trabajos.

useSeoMeta() es el que debes usar para SEO y meta etiquetas sociales. Es una API plana y type-safe con parámetros tipados. Evidence for this claim useSeoMeta is a typed Nuxt API for SEO and social meta tags. Scope: Current Nuxt composable. Confidence: high · Verified: Nuxt: useSeoMeta Ayuda a evitar el clásico error de Open Graph de usar name cuando necesitabas 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() es la herramienta de head de propósito general para todo lo demás — scripts, etiquetas de enlace, atributos del body y plantillas de título:

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

El patrón de capas fiable es: valores predeterminados estáticos (charset, viewport, favicon) en nuxt.config.ts → plantilla de título para todo el sitio y valores OG globales en app.vue → anulaciones específicas de página mediante useSeoMeta() en el componente de página. Un error común es poner useSeoMeta() en un layout en lugar de en la página, lo que sobrescribe las etiquetas específicas de la página con otras genéricas. Y dado que los motores de búsqueda leen la carga inicial, los metadatos SEO normalmente no necesitan ser reactivos — useServerHead() omite la re-ejecución en el lado del cliente.

Qué API, y qué demuestra realmente:

APIAlcance¿Reactiva?Qué demuestra sobre la salida
useSeoMeta()Solo metadatos SEO/sociales planos y tipadosSí (por defecto)Establece propiedades tipadas correctamente — no que la ruta sea única, canónica o indexable; esa lógica sigue siendo tuya
useHead()Cualquier cosa en <head> — scripts, enlaces, atributos, plantilla de títuloSí (por defecto)Control general de la cabecera; misma advertencia — el uso de la API no es prueba de una respuesta correcta del servidor
useServerHead() / llamadas solo de servidorIgual que arribaNo — solo servidor, omite la re-ejecución del clienteConfirma que la etiqueta se envía una vez en el HTML del servidor; no confirma que la navegación del cliente la restablezca si dependes de ella allí

Llamar a uno de estos composables te dice que la API se ejecutó — no te dice por sí mismo qué emite realmente una respuesta directa del servidor o un cambio de ruta en el lado del cliente. Confírmalo con Ver código fuente o curl, no solo con “llamé a useSeoMeta()”.

El ecosistema de módulos @nuxtjs/seo (Harlan Wilton) — opcional, no núcleo

El núcleo de Nuxt no incluye un sitemap, un robots.txt, generación de imágenes OG ni Schema.org de serie — esos están fuera de las primitivas propias de Nuxt (useHead, useSeoMeta, reglas de ruta, modos de renderizado). La comunidad llena ese vacío con @nuxtjs/seo de Harlan Wilton — un paquete paraguas de terceros instalado por separado (nuxtseo.com, actualmente en v5.x, mantenido activamente, dirigido a Nuxt 3,16+ y Nuxt 4) que agrupa seis módulos. Instalarlo te da sitemap, robots, imagen OG y generación de esquema — no garantiza por sí mismo que la salida sea correcta para tus rutas; verifica lo que produce de la misma manera que verificarías cualquier otra cosa:

MóduloQué hace
@nuxtjs/robotsrobots.txt + meta robots + cabeceras X-Robots-Tag
@nuxtjs/sitemapSitemaps XML automáticos desde páginas + rutas dinámicas
nuxt-og-imageImágenes OG dinámicas (una plantilla Vue → una imagen)
nuxt-schema-orgDatos estructurados Schema.org JSON-LD
nuxt-seo-utilsURL principales, migas de pan, valores predeterminados
nuxt-link-checkerDetección de enlaces rotos en tiempo de compilación

Instala todo el paquete con npx nuxt module add seo, o toma módulos individuales (npx nuxt module add sitemap robots). Algunos comportamientos que vale la pena conocer:

  • @nuxtjs/sitemap se genera automáticamente desde tu directorio pages/ más rutas dinámicas, se divide en un índice de sitemap automáticamente después de 50 000 URLs, admite sitemaps multilingües i18n y tiene soporte integrado de IndexNow. Una cosa a tener en cuenta: Google ignora changefreq y priority; solo importa un lastmod preciso, y solo cuando el contenido cambia realmente.
  • @nuxtjs/robots genera robots.txt, la metaetiqueta robots y la cabecera X-Robots-Tag — y por defecto desautoriza a todos los rastreadores en entornos que no son de producción, que es exactamente el peligro de indexación en staging que afecta a las compilaciones headless. También te da reglas por bot, para que puedas bloquear GPTBot específicamente mientras dejas a todos los demás en paz (sé intencional — bloquea un rastreador de IA y no te citará).
  • nuxt-seo-utils maneja las URL principales y, útilmente, elimina los parámetros de seguimiento (utm_*, fbclid, gclid) de esas URL automáticamente.

nuxt/image y Core Web Vitals

@nuxt/image es el módulo de imágenes: srcset responsivo automático, formatos modernos (WebP/AVIF), optimización integrada a través de proveedores CDN y carga diferida. Dos reglas aportan la mayor parte del valor SEO:

  • Nunca hagas lazy-load de la imagen LCP. Tu imagen principal debe cargarse de forma eager; el lazy-loading retrasa tu Largest Contentful Paint.
  • Siempre establece width y height para que el navegador reserve espacio y no sufras un impacto en Cumulative Layout Shift.
<NuxtImg
  src="/hero.jpg"
  width="1200"
  height="630"
  alt="Descriptive alt text"
  :loading="isHeroImage ? 'eager' : 'lazy'"
  format="webp"
/>

Los objetivos para 2026 (p75): LCP ≤ 2,5 s, INP ≤ 200ms, CLS ≤ 0,1. En aplicaciones Nuxt, el INP es el que tiende a sufrir porque la hidratación crea retraso en la entrada — que es exactamente para lo que sirven Nuxt Islands y <NuxtIsland>.

Nuxt Content + SEO

Si estás usando @nuxt/content (el módulo de contenido markdown/MDX), la integración con @nuxtjs/seo es sencilla pero tiene un detalle de orden: carga @nuxtjs/seo antes de @nuxt/content en tu array de módulos. Luego puedes configurar el SEO en el frontmatter del contenido (title, description, robots, ogImage, schemaOrg) y extraerlo en tu plantilla [slug].vue con useSeoMeta() después de obtener el contenido. Esta es la versión nativa de Nuxt del patrón de CMS headless, y se aplica la misma disciplina de “reconstruir lo que el plugin hacía”.

Errores comunes de SEO en Nuxt

  1. Usar el modo SPA (ssr: false) para contenido que quieres indexar. El error más costoso — y el que te hace invisible para los rastreadores de IA.
  2. URLs relativas para imágenes OG. ogImage debe ser una URL absoluta o las vistas previas sociales se rompen.
  3. useSeoMeta() en un layout en lugar de la página — las etiquetas genéricas sobrescriben las específicas de la página.
  4. No verificar el HTML renderizado — Ver código fuente ≠ DevTools ≠ lo que Google renderizó. Usa URL Inspection.
  5. Bloquear JS/CSS en robots.txt — Google no renderizará desde archivos bloqueados.
  6. Dejar el noindex/disallow de staging en su lugar después del lanzamiento (o, por el contrario, olvidar que @nuxtjs/robots bloquea lo que no es producción por defecto y preguntarte por qué producción está bien pero un entorno personalizado no).
  7. Hacer lazy-load de la imagen LCP — hunde tu LCP.
  8. Faltar width/height en las imágenes — CLS.
  9. changefreq/priority en sitemaps — Google los ignora; solo lastmod cuenta.
  10. Recurrir al renderizado dinámico. Google lo deprecó“dynamic rendering is a workaround and not a long-term solution” (traducción) «el renderizado dinámico es un workaround y no una solución a largo plazo» — y solo sirve a los motores para los que lo configuras, perdiéndote Bing y todos los rastreadores de IA. Con Nuxt nunca lo necesitas: SSR y SSG ya dan a los rastreadores HTML completo.

llms.txt y AEO

llms.txt es un archivo de texto plano — primo de robots.txt — que ayuda a las herramientas de IA a navegar tu contenido. El módulo nuxt-llms genera automáticamente /llms.txt y /llms-full.txt desde Nuxt Content. A finales de 2025, sus principales consumidores son servidores MCP y herramientas de codificación con IA (Cursor, Claude Code) más que ChatGPT o Perplexity directamente, y es más útil para sitios de documentación y blogs técnicos — menos para e-commerce o noticias. Vale la pena añadirlo si eres un sitio de docs/dev; no es una prioridad en otros casos.

Dónde encaja

El SEO en Nuxt es realmente una aplicación concreta de JavaScript SEO a través de las propias convenciones de Nuxt — y se superpone en gran medida con el tema de SEO para un CMS headless cuando tu frontend de Nuxt se alimenta de un backend headless. Los principios no cambian; Nuxt solo te da buenos valores por defecto y un ecosistema de módulos sólido para implementarlos.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.