SEO para Astro

Astro es uno de los frameworks más sólidos para SEO: las páginas se prerenderizan como HTML estático por defecto y solo envían JavaScript donde lo pides, con buenos Core Web Vitals. Pero los valores predeterminados no son garantías, y Astro no escribe por ti las etiquetas meta, el sitemap ni los canonicals. Así ejecuto mi propio sitio Astro y así se consigue una arquitectura correcta.

Publicado por primera vez: 26 jun 2026 · Última actualización: 11 ago 2026 · Avanzado
Idiomas

Astro es una de las mejores opciones de framework para SEO porque prerenderiza como HTML estático por defecto: el contenido está en el HTML sin procesar en el primer rastreo y no hay una cola de renderizado que esperar para esa ruta. Las islas hidratan solo los componentes que marcas con una directiva client, así que la mayor parte de la página se envía sin su propio JS de hidratación (aunque Astro aún puede añadir scripts de página y JS del router en otros lugares). Nada de esto garantiza por sí solo la rastreabilidad, la indexación o las posiciones, así que verifica las rutas desplegadas. Los sitios Astro también obtienen buenos resultados de Core Web Vitals. La contrapartida es que Astro genera HTML limpio, pero no escribe tus etiquetas meta, canonicals, sitemap ni datos estructurados: son pasos de compilación deliberados, y el descubrimiento del sitemap se dirige a rutas generadas estáticamente, por lo que las URL que solo existen en tiempo de ejecución necesitan un tratamiento explícito. Las Server Islands (que requieren un adaptador) y View Transitions son seguras para SEO cuando entiendes qué obtienen realmente los rastreadores. Ejecuto patrickstox.com con Astro, así que este es el stack que realmente utilizo.

TL;DR — Astro está bien preparado arquitectónicamente para SEO: las páginas y los endpoints se prerenderizan como HTML estático de forma predeterminada, así que no hay que esperar una segunda oleada de la cola de renderizado para ese contenido. Pero es una configuración predeterminada, no una garantía universal, y el HTML estático o generado por servidor no demuestra por sí solo la rastreabilidad, la indexación, las posiciones ni los Core Web Vitals de tus URL de producción. La arquitectura de islas hidrata solo los componentes que marcas con una directiva client:*; todo lo demás envía HTML sin su propio JS de hidratación, aunque los scripts de página, otras islas y las mejoras del router pueden añadir JavaScript en otros lugares de la página. Astro no genera automáticamente etiquetas meta, canonicals, sitemaps ni datos estructurados: conéctalos explícitamente, idealmente validados mediante Content Collections y Zod. Las Server Islands (que requieren un adaptador) sirven la carcasa estática con contenido de reserva en el documento inicial y obtienen después el contenido diferido de forma independiente: verifica qué recupera realmente cada rastreador en vez de suponerlo. View Transitions utiliza history.pushState y es seguro para SEO; Google rastrea normalmente las páginas MPA subyacentes. Ejecuto patrickstox.com con Astro, y las funciones siguientes son las que realmente uso, validadas contra el sitio desplegado y no solo contra el entorno local.

Evidence for this claim Astro prerenders pages as static HTML by default and only sends client JavaScript for explicitly hydrated components. Scope: Astro default static output and islands architecture. Confidence: high · Verified: Astro: Why Astro

Por qué Astro evita por completo el problema del renderizado de JavaScript

La razón por la que el SEO de JavaScript es difícil es la segunda oleada. Google obtiene primero tu HTML sin procesar y después pone la página en cola para renderizarla en un Chromium sin interfaz más adelante; esa cola es el riesgo. La propia documentación de Google lo describe así: “Googlebot queues all pages with a 200 HTTP status code for rendering unless a robots meta tag tells Google not to index the page. The page may stay on this queue for a few seconds, but it can take longer than that.” (traducción) «Googlebot envía las páginas a la cola de renderizado salvo que una etiqueta meta robots indique lo contrario; la espera puede durar unos segundos o más». En una SPA renderizada en el cliente, tu contenido no existe hasta que se ejecuta esa oleada de renderizado.

El modo de salida predeterminado de Astro es estático: las páginas y los endpoints se prerenderizan como un archivo HTML completo durante la compilación. Por tanto, para una ruta que funciona con ese modo predeterminado, el HTML sin procesar es la página renderizada. Evidence for this claim Astro uses static output and prerenders routes at build time by default. Scope: Astro default output mode; routes can opt out of prerendering. Confidence: high · Verified: Astro: On-demand rendering No hay una segunda oleada que esperar para esa ruta, porque no queda nada por ejecutar. Googlebot ve todo el contenido en la primera petición. Como dice Joost de Valk (fundador de Yoast): “From an SEO perspective, static HTML on a CDN is a better starting point than most CMSes will ever give you.” (traducción) «Desde una perspectiva de SEO, el HTML estático en una CDN es un punto de partida mejor del que la mayoría de los CMS llegará a ofrecerte».

Ese es el comportamiento predeterminado, pero no una propiedad universal de todas las rutas. Establece output: 'server' y el valor predeterminado cambia al renderizado bajo demanda (más adelante hablaremos de ello); incluso en un proyecto cuyo valor predeterminado es estático, un adaptador permite que una ruta individual se excluya mediante export const prerender = false. Nada de esto está garantizado solo por la arquitectura: el HTML estático o de servidor, las islas y los adaptadores no garantizan por sí mismos la rastreabilidad, la indexación, las posiciones ni los Core Web Vitals. Todo depende de la ruta desplegada y del rastreador concreto, así que verifícalo en vez de suponer que el framework se encarga.

Esto también ayuda con los rastreadores que no pueden renderizar en absoluto. Google señala claramente que “not all bots can run JavaScript” (traducción) «no todos los bots pueden ejecutar JavaScript», y esa es la realidad de 2026 para la mayoría de los rastreadores de IA y muchas herramientas de terceros. La salida HTML-first de Astro es legible para todos ellos cuando realmente está prerenderizada, no solo para Googlebot. (Este es el mismo punto que planteo en SEO para un CMS headless: el modo de renderizado es el producto.)

Arquitectura de islas: JS solo donde lo pides

Astro renderiza tus componentes como HTML y, en sus propias palabras, envía “just HTML & CSS, stripping out all client-side JavaScript automatically.” (traducción) «solo HTML y CSS, eliminando automáticamente todo el JavaScript del lado del cliente». La interactividad es opcional. Marcas un componente con una directiva client:*client:load, client:idle o client:visible— y solo esa isla se hidrata con JavaScript. Todo lo demás permanece como HTML estático. Evidence for this claim Astro client directives selectively hydrate interactive islands while other components remain static HTML. Scope: Astro islands and client directives. Confidence: high · Verified: Astro: Islands

Para SEO, esto es casi ideal. El contenido que Googlebot necesita indexar es HTML simple y tus widgets interactivos no lo lastran. client:visible es especialmente útil: un componente situado bajo el pliegue ni siquiera empieza a hidratarse hasta que aparece al hacer scroll, así que nunca bloquea tu LCP. El concepto procede de Jason Miller (creador de Preact), que describió “rendering HTML pages on the server, and inject[ing] placeholders or slots around highly dynamic regions” (traducción) «renderizar páginas HTML en el servidor e inyectar marcadores de posición o espacios alrededor de regiones muy dinámicas» para la hidratación selectiva.

Dos matices que conviene precisar, porque la cobertura de la competencia tiende a mezclarlos:

  • client:only es otra cosa. A diferencia de client:load, client:idle y client:visible, un componente client:only omite por completo el renderizado en el servidor: no produce HTML en el servidor. Cualquier contenido indexable colocado solo dentro de un componente client:only no está en el documento que obtiene Googlebot; solo existe después de que el navegador lo hidrate. No pongas ahí el contenido principal.
  • Esto es hidratación selectiva, no resumabilidad. Astro vuelve a ejecutar desde cero el código de cliente de cada isla en el navegador; no reanuda el estado de ejecución serializado en el servidor como hace un modelo de resumabilidad (por ejemplo, el de Qwik). En los textos se confunden ambos conceptos, pero no son el mismo mecanismo.
Evidence for this claim A client:only component skips server rendering, so indexable content placed only inside it cannot be assumed to exist in the initial page HTML. Scope: client and server islands Confidence: high · Verified: Template directives reference

Además, un componente que no se hidrata no representa todo el panorama de JavaScript de una página. «Zero JS» describe un componente sin una directiva client:*; Astro aún puede enviar etiquetas <script> a nivel de página, el router de View Transitions y otras islas en otros lugares de la misma página. Describe lo que se envía por componente o ruta, no como una afirmación general sobre toda la página.

Lo que Astro NO hace automáticamente

Astro genera HTML semántico limpio y nada más en cuanto a SEO. No hay metadatos, canonical, sitemap ni datos estructurados de serie. El mito de que «Astro está automáticamente optimizado para SEO» es exactamente eso: un mito. Tú te encargas de:

  • Etiquetas meta (title, description, Open Graph, Twitter)
  • URL canonical
  • El sitemap (mediante la integración oficial)
  • Datos estructurados / JSON-LD
  • robots.txt

Astro es la mejor base que he utilizado, pero es una base, no una casa terminada.

El sitemap: @astrojs/sitemap

Instálalo con npx astro add sitemap. Rastrea tus rutas generadas estáticamente y emite un archivo sitemap-index.xml junto con archivos sitemap-0.xml divididos en fragmentos durante la compilación. Hay dos cosas que suelen dar problemas:

Evidence for this claim Astro's official sitemap integration generates sitemap files from statically generated routes. Scope: Astro @astrojs/sitemap integration. Confidence: high · Verified: Astro: Sitemap integration
  • **Debes establecer site: en astro.config.mjs. Sin ello, la integración no genera nada silenciosamente. Es la causa más habitual de «¿dónde está mi sitemap?».
  • Debes añadir tú mismo la línea del sitemap a robots.txt. Astro no lo hace.

Para controlarlo, filter() excluye rutas (páginas de vista previa o borrador, justo para lo que lo uso en este sitio), serialize() permite establecer lastmod, changefreq y priority, y la opción i18n emite entradas hreflang en el sitemap. Esto es lo que especifica la documentación actual de @astrojs/sitemap; confirma el comportamiento frente a tu versión instalada si utilizas una versión antigua, porque el comportamiento de la integración ha cambiado entre versiones principales.

El alcance que confunde a la gente: el descubrimiento de la integración se dirige a las rutas generadas estáticamente. Si alguna de tus URL solo existe en tiempo de ejecución —rutas renderizadas por servidor (output: 'server'), o rutas generadas bajo demanda en lugar de durante la compilación—, no des por hecho que estarán en el sitemap. Añádelas explícitamente con customPages y abre realmente sitemap-index.xml después de una compilación para confirmar que están ahí. No aceptes sin más que «la integración se encarga» de algo que no sea una ruta estática de compilación.

Etiquetas meta y canonical: el patrón BaseLayout

Astro no tiene un componente <Head> especial: controlas directamente <head> en los archivos .astro. El patrón estándar (y el que uso yo) es un único BaseLayout.astro que acepta title, description y canonicalURL como props y escribe el head. Establece explícitamente el canonical en cada página y mantenlo coherente con og:url. No necesitas una biblioteca, pero el paquete comunitario astro-seo (npm) es un wrapper cómodo de un componente para title, description, OG, Twitter y canonical si quieres usarlo.

Content Collections como red de seguridad SEO

Esta es la función de Astro para SEO que menos se valora. Content Collections es una capa de contenido con tipos seguros para Markdown, MDX y JSON, con validación de esquemas Zod. Eso permite hacer que title y description sean campos obligatorios; si a una página le falta uno, la compilación falla. No puedes enviar accidentalmente una página sin título. Las funciones de consulta (getCollection(), getEntry()) generan páginas estáticas durante la compilación, así que al desplegarse la salida es HTML simple. Y como MDX conserva el Markdown sin procesar como fuente de verdad, esos archivos también son contenido fuente limpio para los rastreadores de IA y patrones del tipo llms.txt. Este mismo sitio se construye con Content Collections y frontmatter validado con Zod.

astro:assets: imágenes bien hechas (con una trampa)

El componente <Image /> convierte automáticamente a WebP, infiere las dimensiones para “avoid Cumulative Layout Shift (CLS),” (traducción) «evitar el desplazamiento acumulativo del diseño (CLS)», establece loading="lazy" de forma predeterminada y requiere alt: que falte alt es un error de compilación. <Picture /> amplía esto con elementos <source> AVIF/WebP y de reserva.

La trampa es que el loading="lazy" automático no es adecuado para tu imagen LCP (normalmente el hero). Cargar de forma diferida la imagen más importante retrasa su carga. En las imágenes visibles en la primera pantalla, sobrescribe con loading="eager" y fetchpriority="high". Las imágenes remotas necesitan width y height explícitos.

Server Islands: lo que realmente ven los rastreadores

Las Server Islands (Astro 4.12+) son la función que más suelen entender mal las guías de la competencia. Con server:defer, un componente se renderiza en el servidor de forma independiente de la página principal. La carcasa estática se sirve inmediatamente; según la documentación de Astro: “Your page will be rendered immediately with any specified fallback content as a placeholder. Then, the component’s own contents are fetched on the client and displayed when available.” (traducción) «Astro muestra primero el contenido de reserva y obtiene después el contenido propio de la isla en el cliente cuando está disponible».

Hay que ser precisos en dos aspectos. Primero, las Server Islands requieren un adaptador: son una función bajo demanda, no algo que una compilación puramente estática produzca por sí sola. Segundo, la secuencia es esta: el documento inicial se envía con el contenido de reserva que hayas configurado y el contenido real de la isla es una petición independiente y separada que se obtiene después de cargar la página mediante su propio endpoint. Ese es el límite estricto de lo que contiene el primer documento; no generalizaría más sobre lo que hace después cada rastreador concreto sin probar directamente tus propias URL desplegadas.

La consecuencia SEO es concreta: el HTML estático que un rastreador lee en esa primera petición contiene el contenido de reserva, no el contenido diferido de la isla. Eso es perfecto para el propósito de las Server Islands: información personalizada y específica de la sesión (estado de inicio de sesión, cantidad del carrito, recomendaciones) que de todos modos no debería almacenarse en caché ni indexarse. Es incorrecto para el contenido principal indexable. Coloca cualquier cosa que deba posicionarse en la plantilla principal de Astro y deja que las Server Islands gestionen los elementos dinámicos que la rodean.

Modos de salida: estático frente a servidor y la sustitución por ruta

El modo de salida predeterminado de Astro es static: las páginas y los endpoints se prerenderizan como HTML durante la compilación. Establece output: 'server' en astro.config.mjs y el valor predeterminado cambia al renderizado bajo demanda: las páginas se renderizan en cada petición (con un adaptador), algo útil para autenticación, datos en tiempo real o personalización más allá de lo que cubren las Server Islands. En cualquier caso, puedes sustituir el valor predeterminado por ruta: en un proyecto cuyo valor predeterminado es estático, export const prerender = false activa el renderizado bajo demanda para una ruta; en uno cuyo valor predeterminado es de servidor, export const prerender = true la devuelve al prerenderizado durante la compilación. Así que «mi sitio es estático» o «mi sitio usa SSR» rara vez es cierto para todas las rutas: comprueba la configuración por ruta, no solo la configuración superior. Evidence for this claim Astro uses static output and prerenders routes at build time by default. Scope: Astro default output mode; routes can opt out of prerendering. Confidence: high · Verified: Astro: On-demand rendering

Desde un punto de vista de SEO puro, el HTML prerenderizado y el HTML bajo demanda son equivalentes: ambos entregan HTML completo al primer request de un rastreador, una vez que has confirmado que la ruta devuelve un 200 con todo el marcado. Las rutas bajo demanda pueden transmitir su HTML, y los datos lentos o las condiciones de red pueden retrasar fragmentos posteriores, así que una respuesta transmitida no demuestra automáticamente que haya llegado todo el contenido: compruébalo, no lo supongas. La diferencia real entre ambos modos es operativa: el contenido prerenderizado permanece fijo hasta la siguiente compilación —o hasta una actualización en tiempo de ejecución configurada por separado— y se sirve directamente desde el borde de la CDN; el contenido bajo demanda siempre está actualizado, pero depende de que el adaptador y el entorno de ejecución funcionen bien en producción. No lo trates como una decisión de SEO: elige según la frescura de los datos y las operaciones, y después valida las rutas desplegadas, sus estados, redirecciones y cabeceras en lugar de extrapolar desde lo que funcionó en desarrollo local.

View Transitions: seguras para SEO pese a la sensación de SPA

El <ClientRouter /> de Astro (antes <ViewTransitions />) ofrece navegación suave con sensación de SPA mediante la API View Transitions del navegador y la History API. El hecho clave es que navega con history.pushState, justo lo que recomienda Google para la navegación del lado del cliente; Google advierte que las URL basadas en fragmentos (#hash) son algo que “can’t reliably resolve” (traducción) «no puede resolver de forma fiable». Es crucial entender que View Transitions es una mejora del lado del navegador. Cuando Googlebot rastrea, solicita cada URL y recibe una página HTML normal y completa: la MPA subyacente no se modifica. Las transiciones solo afectan a lo que ve una persona en el navegador.

Así que no: View Transitions no convierte tu sitio Astro en una SPA ni rompe el SEO. Hay una carencia digna de mención: la documentación de View Transitions de Astro no tiene ninguna sección de SEO, probablemente por eso persiste el mito de que «rompe el SEO». Para verificarlo en tu sitio, obtén directamente varias URL y confirma que cada una devuelve HTML completo: no lo aceptes sin comprobar tu propio despliegue.

Errores habituales de SEO en Astro

  1. Suponer que Astro gestiona el SEO por ti. Gestiona el HTML. Las meta, los canonicals, el sitemap y el schema son responsabilidad tuya.
  2. Olvidar site: en la configuración: el sitemap no se genera y no avisa.
  3. No añadir el sitemap a robots.txt: Astro no lo hará.
  4. Cargar de forma diferida la imagen LCP: sustituye el valor predeterminado del hero por eager y fetchpriority.
  5. Colocar contenido indexable en una Server Island: los rastreadores ven el contenido de reserva, no el contenido real, y las Server Islands requieren un adaptador desde el principio.
  6. Perseguir una puntuación perfecta de Lighthouse y detenerse ahí. La velocidad es una señal de posiciones, no la señal de posiciones. Una página rápida y vacía no se posiciona: el contenido, los enlaces y E-E-A-T siguen haciendo el trabajo pesado.
  7. Colocar contenido indexable solo dentro de un componente client:only. A diferencia de las demás directivas client:*, client:only omite por completo el renderizado en el servidor: no hay HTML para ese componente hasta que el navegador lo hidrata.
  8. Tratar «Astro es estático/rápido» como una garantía de resultado. El HTML estático o bajo demanda, las islas y los adaptadores son mecanismos: por sí solos no garantizan rastreabilidad, indexación, posiciones ni Core Web Vitals. Valida la ruta desplegada, no el diagrama de arquitectura.

Dónde encaja esto en el grupo de contenidos

Astro es una respuesta concreta y excepcionalmente favorable para SEO a las preguntas que plantea JavaScript SEO sobre el renderizado, y un frontend popular para configuraciones de CMS headless. La parte de rendimiento conecta directamente con Core Web Vitals en el grupo de rendimiento web, y la disciplina de comprobar si tu contenido está realmente en el HTML es la misma que aparece en los grupos de rastreo e indexación.

Add an expert note

Pin an expert quote

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