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.
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 es una excelente opción para SEO. De forma predeterminada convierte tus páginas en archivos HTML simples por adelantado, así que cuando llega Google —o cualquier bot— tu contenido ya está ahí: no hay que esperar a que se ejecute JavaScript. También es muy rápido. Lo importante es esto: Astro te proporciona HTML limpio, pero no añade automáticamente los títulos de página, el sitemap ni las etiquetas canonical. Tienes que configurarlos tú mismo (es fácil).
Qué significa «Astro SEO»
Astro es un framework web para crear sitios web. Su gran idea es «menos JavaScript». Mientras que frameworks como React o Next.js suelen construir la página en tu navegador usando JavaScript, Astro construye tus páginas como archivos HTML simples durante la compilación y envía muy poco JavaScript, salvo que una parte de la página realmente lo necesite. 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
Esa única diferencia explica por qué Astro es tan favorable para los motores de búsqueda. Cuando un motor de búsqueda rastrea una página, quiere leer tu contenido. En un sitio con mucho JavaScript, a veces el contenido aún no está en la página: el bot tiene que ejecutar primero el JavaScript, y eso puede retrasarse. Con Astro, el contenido ya está en el HTML en el momento en que carga la página. No hay nada que esperar.
Yo ejecuto mi propio sitio, patrickstox.com, con Astro, así que esto no es teoría para mí. Es el stack sobre el que realmente construyo.
Por qué Astro es bueno para SEO
- El contenido está en el HTML desde el principio. No hay retraso de renderizado ni contenido ausente.
- Es rápido. Los sitios Astro son ligeros y suelen obtener muy buenos resultados en las métricas de experiencia de página de Google (Core Web Vitals).
- Cada página tiene su propia URL real. No hay un enrutamiento sofisticado de aplicación de una sola página que pueda confundir a los rastreadores.
- El JavaScript solo se carga donde hace falta. Una galería de fotos o un cuadro de búsqueda puede ser interactivo sin ralentizar el resto de la página.
Lo que Astro NO hace por ti
Esto confunde a mucha gente. «Astro está optimizado para SEO» solo es cierto a medias. Astro te proporciona una base limpia, pero no hace automáticamente lo siguiente:
- Escribir los títulos y las meta descripciones de tus páginas.
- Generar un sitemap (añades un plugin oficial gratuito para ello). 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
- Añadir etiquetas canonical (que indican a Google cuál es la versión «oficial» de una página).
- Añadir datos estructurados (el código que impulsa los resultados enriquecidos).
- Crear un archivo robots.txt.
Nada de esto es difícil: simplemente depende de ti configurarlo. Piensa en Astro como en una cocina estupenda: los electrodomésticos son excelentes, pero aun así tienes que cocinar.
La lista de comprobación inicial sencilla
- Añade un sitemap con el plugin oficial
@astrojs/sitemap. - Establece un
title, unadescriptiony una URLcanonicalen cada página (normalmente desde un archivo de layout compartido). - Usa el componente integrado
<Image />de Astro para las fotos: hace que carguen rápido y evita que la página dé saltos. - Coloca un archivo
robots.txten tu carpetapublic/.
¿Quieres la versión profunda —Server Islands, View Transitions, renderizado estático frente a servidor y los errores exactos que debes evitar? Cambia a la pestaña Avanzado. Para conocer el panorama general de cómo los motores de búsqueda gestionan JavaScript, consulta JavaScript SEO.
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 AstroTL;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 utilizahistory.pushStatey 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.
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:onlyes otra cosa. A diferencia declient:load,client:idleyclient:visible, un componenteclient:onlyomite por completo el renderizado en el servidor: no produce HTML en el servidor. Cualquier contenido indexable colocado solo dentro de un componenteclient:onlyno 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.
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:
- **Debes establecer
site:enastro.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
- Suponer que Astro gestiona el SEO por ti. Gestiona el HTML. Las meta, los canonicals, el sitemap y el schema son responsabilidad tuya.
- Olvidar
site:en la configuración: el sitemap no se genera y no avisa. - No añadir el sitemap a robots.txt: Astro no lo hará.
- Cargar de forma diferida la imagen LCP: sustituye el valor predeterminado del hero por
eageryfetchpriority. - 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.
- 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.
- Colocar contenido indexable solo dentro de un componente
client:only. A diferencia de las demás directivasclient:*,client:onlyomite por completo el renderizado en el servidor: no hay HTML para ese componente hasta que el navegador lo hidrata. - 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.
Antipatrones de SEO en Astro
Errores concretos que realmente veo en sitios Astro, no situaciones hipotéticas. Cada uno es prevención, no diagnóstico: detecta el problema antes de publicarlo.
Tratar Astro como «optimizado para SEO» de serie
Astro proporciona HTML estático rápido y limpio, y eso es realmente una gran ventaja inicial, pero no es lo mismo que tener etiquetas meta, canonicals, un sitemap o datos estructurados. Por qué está mal: los equipos publican páginas sin variación de <title>, sin canonical y sin sitemap porque «Astro gestiona el SEO», y después se preguntan por qué nada se indexa como esperaban. Qué hacer en su lugar: conecta desde el primer día los props de title, description y canonical de BaseLayout.astro, añade @astrojs/sitemap y trata esos elementos como pasos de compilación obligatorios, no como valores predeterminados.
Olvidar site: en astro.config.mjs
Este es el informe más común de «por qué está vacío mi sitemap». Por qué está mal: @astrojs/sitemap necesita una URL absoluta del sitio para construir entradas <loc> absolutas; sin establecer site:, la integración no produce nada silenciosamente (sin error ni advertencia). Qué hacer en su lugar: establece site: en astro.config.mjs antes de instalar la integración del sitemap y comprueba que sitemap-index.xml contiene realmente URL después de la siguiente compilación.
Omitir el sitemap de robots.txt
Instalar @astrojs/sitemap no añade una línea Sitemap: a robots.txt: es un paso manual separado que la gente supone automático. Por qué está mal: los motores de búsqueda aún pueden encontrar el sitemap si lo envías a Search Console, pero pierdes la ruta de descubrimiento pasivo en la que confían otros bots (y los rastreadores relacionados con Bing/IndexNow). Qué hacer en su lugar: añade Sitemap: https://yoursite.com/sitemap-index.xml a tu robots.txt en public/ y confirma que responde después del despliegue.
Dejar loading="lazy" como valor predeterminado en la imagen hero
El componente <Image /> de Astro carga las imágenes de forma diferida por defecto, lo que es correcto para las imágenes que están bajo el pliegue y incorrecto para la imagen que normalmente es tu elemento LCP. Por qué está mal: cargar el hero de forma diferida retrasa incluso el inicio de la petición de esa imagen en el navegador, lo que perjudica directamente tu puntuación de Largest Contentful Paint. Qué hacer en su lugar: sustituye explícitamente la imagen hero o visible en la primera pantalla por loading="eager" y fetchpriority="high", y deja todas las demás imágenes con el valor predeterminado lazy.
Poner contenido indexable dentro de una Server Island
server:defer está pensado para contenido personalizado y específico de la sesión —cantidades del carrito, estado de inicio de sesión y recomendaciones—, no para nada que quieras posicionar. Por qué está mal: el HTML estático que lee un rastreador contiene el contenido de reserva especificado para la isla, no lo que se obtiene en el cliente después de cargar la página, así que cualquier contenido principal que coloques ahí es invisible para los motores de búsqueda en el primer rastreo. Qué hacer en su lugar: mantén el contenido que deba posicionarse en la plantilla principal de Astro y reserva las Server Islands estrictamente para los elementos dinámicos y personalizados que no deberían indexarse.
Suponer que una puntuación rápida de Lighthouse es la meta final
Los sitios Astro suelen ofrecer buenos Core Web Vitals casi de serie, y es tentador detenerse ahí. Por qué está mal: la velocidad es una señal de posiciones entre muchas; una página rápida, vacía o superficial sigue sin superar a una página más lenta con mejor contenido, enlaces y profundidad temática. Qué hacer en su lugar: trata el rendimiento como el requisito básico que Astro te da gratis y dedica el esfuerzo de optimización real a la calidad del contenido, los enlaces internos y el trabajo de datos estructurados y meta que Astro no hace por ti.
Suponer que «estático por defecto» es cierto para todas las rutas
El modo de salida estático de Astro es el predeterminado, pero es un valor predeterminado, no una propiedad universal: output: 'server' lo cambia y prerender se puede establecer por ruta en ambas direcciones. Por qué está mal: los equipos describen todo su sitio como «estático» o «SSR» a partir de la configuración superior y nunca comprueban las rutas individuales; después se sorprenden cuando una ruta se comporta de otra manera en producción. Qué hacer en su lugar: comprueba la configuración prerender por ruta para todo aquello sobre lo que estés razonando y valida la respuesta real (código de estado, marcado completo y comportamiento de redirección) en la URL desplegada, no en el archivo de configuración.
Poner el contenido solo dentro de un componente client:only
client:only no es lo mismo que client:load, client:idle o client:visible: omite por completo el renderizado en el servidor. Por qué está mal: un componente que utiliza client:only no produce HTML en el servidor, así que cualquier contenido indexable colocado solo ahí es invisible para un rastreador que lea la respuesta sin procesar, y es fácil recurrir a client:only por «simplicidad» sin darse cuenta del coste SEO. Qué hacer en su lugar: renderiza el contenido principal en un componente renderizado en el servidor o en la plantilla de la página; reserva client:only para widgets de interacción que no contengan nada indexable.
Resumen de IA
Una versión condensada del contenido avanzado:
- El modo de salida predeterminado de Astro prerenderiza como HTML estático durante la compilación: para una ruta que utiliza ese valor predeterminado, el HTML sin procesar es la página terminada, así que el problema de la cola de renderizado de Google —la «segunda oleada»— no se aplica. Es un valor predeterminado, no una propiedad universal:
output: 'server'lo cambia yprerenderpuede sustituirlo por ruta en cualquiera de las dos direcciones. - La arquitectura de islas hidrata solo los componentes marcados con
client:*; un componente sin esa directiva envía HTML sin su propio JS de hidratación (aunque Astro puede añadir scripts de página, otras islas y JS del router en otros lugares).client:onlyes la excepción: omite por completo el renderizado en el servidor, así que el contenido indexable no debería vivir solo ahí. Esto es hidratación selectiva, no resumabilidad.client:visibleevita que el JS de componentes bajo el pliegue bloquee el LCP. - Astro no genera nada automáticamente en materia de SEO: las etiquetas meta, los canonicals, el sitemap, los datos estructurados y robots.txt son pasos de compilación deliberados. «Astro está automáticamente optimizado para SEO» es un mito.
@astrojs/sitemapdescubre rutas generadas estáticamente, pero debes establecersite:en la configuración (o no hará nada silenciosamente), añadir tú mismo la línea del sitemap a robots.txt e incluir explícitamente cualquier URL que solo exista en tiempo de ejecución mediantecustomPages.- Content Collections + Zod puede hacer que
titleydescriptionsean obligatorios y que la compilación falle si falta alguno: es una red de seguridad SEO. astro:assets<Image>convierte a WebP, establece dimensiones (evita CLS), carga de forma diferida por defecto y exigealt. Sobrescribe la imagen LCP conloading="eager"yfetchpriority="high".- Las Server Islands (
server:defer) requieren un adaptador, sirven inmediatamente la carcasa estática y el contenido de reserva en el documento inicial y después obtienen la isla de forma independiente. Los rastreadores que leen ese primer documento ven el contenido de reserva, no la isla: nunca pongas ahí contenido indexable. - La salida estática y la salida bajo demanda (de servidor) son equivalentes para SEO una vez verificadas: ambas entregan HTML completo a los rastreadores en la primera petición, pero las rutas bajo demanda pueden transmitir el contenido, así que confirma que la respuesta llega completa; elige el modo según la frescura de los datos y las operaciones, no según el SEO.
- View Transitions (
<ClientRouter />) utilizahistory.pushStatey es seguro para SEO; Google rastrea normalmente las páginas MPA subyacentes. Es una mejora del navegador, no una conversión a SPA. - Nada de lo anterior garantiza un resultado: el HTML estático o de servidor, las islas y los adaptadores son mecanismos, no pruebas de rastreabilidad, indexación, posiciones ni Core Web Vitals. Valida la ruta desplegada.
- Astro obtiene buenos resultados de Core Web Vitals en su propio benchmark de 2023: más del 50 % de los sitios Astro superaron la evaluación de CWV de Google, muy por encima de la referencia del sector en ese momento; trátalo como un dato fechado, no como una garantía vigente.
Documentación oficial
Documentación de fuentes primarias de Astro y de los motores de búsqueda.
Astro
- Arquitectura de islas: cómo Astro elimina el JS del lado del cliente e hidrata solo los componentes interactivos.
- Referencia de directivas de plantillas:
client:load/idle/visible/onlyyserver:defer, incluido lo que omiteclient:only. - Optimización de imágenes (astro:assets): los componentes
<Image>/<Picture>, WebP, dimensiones y CLS. - @astrojs/sitemap: generación automática del sitemap,
filter,serializeei18n. - Server Islands:
server:defer, el requisito del adaptador, el contenido de reserva y la obtención diferida en el cliente. - Renderizado bajo demanda: los modos de salida
static/server,prerenderpor ruta y transmisión de HTML. - Referencia de enrutamiento: cómo se prerenderizan por defecto las páginas y los endpoints.
- Referencia de la API de ejecución de Astro: gestión de
Response/redirecciones y códigos de estado predeterminados. - Content Collections: contenido con tipos seguros y validación de esquemas Zod.
- View Transitions:
<ClientRouter />y navegación mediante la History API.
- Conceptos básicos del SEO de JavaScript: la cola de renderizado, los enlaces rastreables, la History API y la advertencia de que «no todos los bots ejecutan JavaScript».
- Guía detallada de cómo funciona la Búsqueda de Google: rastreo → renderizado → indexación y cómo el SSG elimina el paso de renderizado.
Bing / Microsoft
- IndexNow / indexnow.org: el protocolo push que encaja bien con un despliegue Astro estático (conéctalo al paso de publicación para que Bing y Yandex conozcan inmediatamente las páginas nuevas).
Citas de las fuentes
Declaraciones públicas de la documentación de Astro, Google y profesionales conocidos. Cada enlace de los motores de búsqueda y la documentación es un enlace profundo que salta al pasaje citado de la página de origen.
Google: la cola de renderizado que Astro evita
- “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 pone en cola para renderizar todas las páginas con un código de estado HTTP 200, salvo que una etiqueta meta robots indique a Google que no indexe la página. La página puede permanecer en esta cola unos segundos, pero puede tardar más». Saltar a la cita
- “not all bots can run JavaScript” (traducción) «no todos los bots pueden ejecutar JavaScript»: por qué la salida HTML-first ayuda más allá de Googlebot. Saltar a la cita
Documentación de Astro: islas, imágenes, sitemaps y Server Islands
- “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»: sobre la arquitectura de islas. Saltar a la cita
- “infers image dimensions to avoid Cumulative Layout Shift (CLS).” (traducción) «infiere las dimensiones de las imágenes para evitar el desplazamiento acumulativo del diseño (CLS)»: sobre el componente Image. Saltar a la cita
- “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) «tu página se renderizará inmediatamente con cualquier contenido de reserva especificado como marcador de posición. Después, el propio contenido del componente se obtiene en el cliente y se muestra cuando está disponible»: sobre las Server Islands. Saltar a la cita
Jason Miller (creador de Preact, acuñó el término «arquitectura de islas»)
- La hidratación selectiva funciona mediante “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». — citado en Documentación de Astro: arquitectura de islas
Joost de Valk (fundador de Yoast SEO)
- “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». — Joost.blog: guía completa de SEO para Astro
Lista de comprobación de Astro SEO
Una pasada para confirmar que un sitio Astro está realmente preparado para la búsqueda, no simplemente apoyado en una buena base:
-
site:está establecido enastro.config.mjs(el sitemap no se genera silenciosamente sin ello). -
@astrojs/sitemapestá instalado y la referencia al sitemap se ha añadido manualmente arobots.txt. - Existe un
robots.txtenpublic/y no bloquea nada que quieras indexar. - Cada página establece un
titley unadescriptionúnicos (idealmente mediante unBaseLayout.astrocompartido). - Hay un canonical autorreferente en cada página y coincide con
og:url. - Content Collections utiliza un esquema Zod que hace obligatorios
titleydescription(la compilación falla si faltan). - Las imágenes utilizan
<Image />o<Picture />; todas tienenalt(que falte uno ya es un error de compilación). - La imagen LCP/hero sustituye la carga diferida predeterminada por
loading="eager"yfetchpriority="high". - No hay contenido indexable en una Server Island (
server:defer): los rastreadores ven el contenido de reserva y las Server Islands necesitan un adaptador para funcionar. - No hay contenido indexable que viva solo dentro de un componente
client:only: omite el renderizado en el servidor, así que no hay HTML para él hasta que el navegador lo hidrate. - En cualquier ruta que utilice
output: 'server'o unaprerender = falsepor ruta, confirma que las URL que solo existen en tiempo de ejecución se añaden explícitamente al sitemap (customPages): el descubrimiento automático del sitemap se dirige a rutas generadas estáticamente. - Los datos estructurados (JSON-LD) están en el
<head>renderizado en el servidor. - Si
<ClientRouter />está activado, comprueba algunas URL para confirmar que siguen devolviendo HTML completo en una petición directa. - En las rutas bajo demanda o de servidor: obtén directamente una URL de producción y confirma el código de estado, el comportamiento de redirección y el HTML completo de la respuesta. No extrapoles desde el entorno local, porque el comportamiento del adaptador y del runtime puede ser diferente.
Los modelos mentales
1. El HTML sin procesar es la página terminada, para el valor predeterminado de esa ruta.
El modo de salida estático de Astro significa que no hay una oleada de renderizado que esperar en una ruta prerenderizada: lo que obtiene Googlebot es lo que se indexa. Es un valor predeterminado por ruta, no una garantía para todo el sitio (output: 'server' y el prerender por ruta pueden cambiarlo), así que comprueba la ruta y no solo la configuración superior. Cuando se aplica, View Source es la verdad (lo contrario de una SPA CSR), pero confirma que se aplica antes de tratarlo como un hecho.
2. Una base, no un acabado, y no una garantía de resultado. Astro te da HTML limpio y sólidos mecanismos de rendimiento de forma gratuita. Todo lo que comunica significado a los motores de búsqueda —meta, canonical, sitemap y schema— es un paso deliberado que debes añadir. «Buena arquitectura» ≠ «terminado», y ninguna de las dos cosas demuestra la rastreabilidad, la indexación ni las posiciones: todavía hay que validarlas en el sitio desplegado.
3. Las islas son aditivas, excepto client:only.
La interactividad se sitúa encima del HTML, nunca debajo, con client:load/client:idle/client:visible: esas directivas añaden JS a un componente sin quitar contenido de la base rastreable. client:only rompe ese patrón: omite por completo el renderizado en el servidor, así que no es aditivo, sino un hueco real en el HTML estático salvo que lo tengas previsto. Y la hidratación de islas es selectiva, no resumabilidad: no confundas ambas cosas.
4. La carcasa estática es lo que ven los rastreadores. En las Server Islands, el rastreador lee el contenido de reserva de la carcasa estática, no el contenido diferido. Regla de decisión: el contenido indexable va en la plantilla principal; el contenido personalizado o dinámico va en la isla.
5. La mejora del navegador ≠ un cambio estructural.
View Transitions cambia la experiencia del navegador (navegación suave mediante history.pushState), pero no la experiencia de rastreo (cada URL sigue siendo una página HTML completa). Las mejoras que dejan intacta la MPA subyacente son seguras para SEO.
6. Valida durante la compilación. Content Collections + Zod convierte «recuerda añadir un título» en «la compilación no se publicará sin uno». Introduce los requisitos SEO en el sistema de tipos y dejarán de ser cosas que puedes olvidar.
Astro SEO: resumen práctico
Qué es automático y qué depende de ti
| Aspecto | ¿Lo hace Astro? | Qué haces tú |
|---|---|---|
| Salida HTML estática | ✅ Predeterminada (modo static) | Nada: es el valor predeterminado, pero comprueba prerender por ruta |
| Los componentes no hidratados no envían JS propio | ✅ Islas (excepto client:only) | Usa client:* solo donde haga falta; mantén el contenido indexable fuera de client:only |
| WebP + dimensiones + carga diferida de imágenes | ✅ <Image> | Sustituye la carga de la imagen LCP por eager |
Exigencia de alt | ✅ Error de compilación si falta | Escribe un buen texto alt |
| Sitemap | ⚠️ Plugin, solo rutas estáticas | astro add sitemap + establece site: + customPages para URL que solo existan en tiempo de ejecución |
| Sitemap en robots.txt | ❌ | Añade la línea manualmente |
| Etiquetas meta / canonical | ❌ | Props de BaseLayout.astro |
| Datos estructurados (JSON-LD) | ❌ | Añádelos al <head> |
| robots.txt | ❌ | Archivo en public/ |
| Garantía de resultado (rastreabilidad/posiciones/CWV) | ❌: solo mecanismos | Valida tú mismo la ruta desplegada |
Modos de salida
| Modo | Configuración | SEO (una vez verificado) | Úsalo para |
|---|---|---|---|
| static (predeterminado) | — | ✅ HTML completo en la primera petición | La mayoría del contenido; servido desde el borde de la CDN |
| server | output: 'server' | ✅ Igual que static para los rastreadores | Autenticación, tiempo real y personalización |
| Sustitución por ruta | export const prerender = false (predeterminado estático) o = true (predeterminado de servidor) | ✅ | Mezclar rutas prerenderizadas y bajo demanda |
Directivas de islas
client:load: hidrata inmediatamente.client:idle: hidrata cuando el navegador está inactivo.client:visible: hidrata al aparecer al hacer scroll (ideal bajo el pliegue; protege el LCP).client:only: omite por completo el renderizado en el servidor. No hay HTML para este componente hasta que el navegador lo hidrata; no es aditivo como los demás.
Reglas rápidas
- Falta
site:→ no hay sitemap (silenciosamente). - Contenido indexable en una Server Island → el rastreador ve el contenido de reserva; las Server Islands necesitan un adaptador.
- Contenido indexable solo dentro de
client:only→ no hay HTML para él, punto. - El sitemap cubre rutas estáticas → añade las URL que solo existan en tiempo de ejecución mediante
customPages. - View Transitions utiliza
history.pushState→ es seguro para SEO, con la MPA debajo. - La salida estática o de servidor y las islas son mecanismos, no garantías: valida la ruta desplegada, el código de estado y el HTML completo antes de afirmar un resultado.
- Una página rápida pero vacía sigue sin posicionarse: la velocidad es una señal, no la señal.
Audita el HTML compilado de Astro
Ejecuta esto después de astro build. Comprueba el artefacto que reciben los rastreadores, no el árbol de componentes de origen:
find dist -name '*.html' -type f | while IFS= read -r file; do
canonicals=$(grep -Eio '<link[^>]+rel=["'"']canonical["'"'][^>]*>' "$file" | wc -l | tr -d ' ')
titles=$(grep -Eio '<title>[^<]*</title>' "$file" | wc -l | tr -d ' ')
if [ "$canonicals" -ne 1 ] || [ "$titles" -ne 1 ]; then
printf '%s\ttitles=%s\tcanonicals=%s\n' "$file" "$titles" "$canonicals"
fi
doneUn resultado vacío significa que cada archivo HTML generado tiene exactamente un título y un canonical; no valida que sus valores sean correctos, así que toma muestras por separado. Esto solo comprueba el artefacto de compilación: no dice nada sobre las rutas bajo demanda (output: 'server') ni sobre las Server Islands, que no existen como archivos estáticos.
Comprueba rutas activas en producción
Para cualquier elemento que se renderice bajo demanda —rutas output: 'server', prerender = false por ruta o Server Islands—, la comprobación del resultado de compilación anterior no se aplica. Comprueba en su lugar la respuesta desplegada real:
# Replace with your real URLs
for url in "https://example.com/" "https://example.com/some-server-route/"; do
echo "== $url =="
curl -sS -D - -o /dev/null "$url" | grep -Ei '^(HTTP|location|cache-control):'
doneBusca el código de estado que esperas (200 para una página activa, un código de redirección real si redirige; no supongas 302 frente a 301 sin comprobarlo) y confirma que curl -sS "$url" devuelve marcado completo, no una carcasa de reserva, si estás comprobando una página que incluye una Server Island. Hazlo contra producción, no contra astro dev: el comportamiento del adaptador y del runtime puede ser diferente.
Herramientas para un sitio Astro
@astrojs/sitemap: la integración oficial del sitemap (astro add sitemap). No olvidessite:en la configuración.astro-seo(npm): componente comunitario opcional que reúne title, description, Open Graph, tarjetas de Twitter y canonical en una sola etiqueta.astro-seo-schema(npm): helper tipado de datos estructurados JSON-LD para Astro.- astro:assets
<Image>/<Picture>: optimización de imágenes integrada (WebP/AVIF, dimensiones, carga diferida y exigencia dealt). - Inspección de URL (Google Search Console): confirma que tu contenido está en el HTML rastreado (con Astro debería estar ya en View Source; es una comprobación rápida),
- Un rastreador que renderice JS: Ahrefs Site Audit o Screaming Frog para verificar la paridad entre el resultado sin procesar y el renderizado en todo el sitio (en rutas prerenderizadas deberían coincidir: confírmalo, no lo supongas, y comprueba por separado las rutas bajo demanda o con Server Islands).
- IndexNow: conéctalo al paso de despliegue o publicación para que Bing y Yandex conozcan inmediatamente las páginas estáticas nuevas.
Ponte a prueba: Astro SEO
Cinco preguntas rápidas sobre cómo la arquitectura de Astro afecta al SEO. Elige una respuesta para cada una y después comprueba el resultado.
Recursos que merecen tu tiempo
Mis artículos relacionados
- JavaScript SEO: A Definitive Guide: los fundamentos del renderizado que explican por qué la salida HTML-first de Astro es una ventaja tan grande.
- The Beginner’s Guide to Technical SEO: dónde encaja la elección de framework en el SEO técnico general.
Mis charlas
- How Search Works (SlideShare): mi explicación del rastreo, el renderizado, la indexación y las posiciones, el flujo que el valor predeterminado SSG de Astro acorta. (Aviso permanente: “This is my understanding of systems… not going to be 100% complete or accurate.” (traducción) «Esta es mi comprensión de los sistemas… no va a ser 100 % completa ni exacta.»)
Del sector en general
- Documentación de Astro: arquitectura de islas: la explicación canónica de cómo Astro elimina el JS del lado del cliente.
- Documentación de Astro: @astrojs/sitemap: configuración oficial, el requisito
site:y las opcionesfilter/serialize/i18n. - Documentación de Astro: Server Islands:
server:defer, contenido de reserva y el comportamiento de obtención en cliente que los rastreadores no ven. - Joost de Valk: Astro SEO Complete Guide: la guía profesional más autorizada, de manos del fundador de Yoast; sólida en patrones modernos preparados para IA e IndexNow.
- Google Search Central: Understand JavaScript SEO Basics: la cola de renderizado, los enlaces rastreables y la orientación sobre History API que sigue View Transitions de Astro.
- Astro: 2023 Web Framework Performance Report: los datos de Core Web Vitals que comparan Astro con otros frameworks.
- Search Engine Journal: métricas web esenciales, WordPress y Astro: cobertura independiente de la comparación de rendimiento entre Astro y WordPress.
Estadísticas que merece la pena citar
Todas las cifras siguientes proceden del Astro 2023 Web Framework Performance Report (y de la cobertura de SEJ); trátalas como benchmarks de la era de 2023, no como cifras actuales.
- Más del 50 % de los sitios Astro supera la evaluación de Core Web Vitals de Google: por encima de la media del sector, de aproximadamente 40,5 %, y Astro y SvelteKit eran los únicos frameworks importantes que superaban esa referencia (Next.js, aproximadamente 25 %; Nuxt, aproximadamente 20 %). Fuente
- Tasa de aprobación de INP del 68,8 % para Astro: atribuida a la arquitectura MPA (sin navegación impulsada por JS), que mantiene libre el hilo principal. Fuente
- Peso mediano de página de 1,65 MB: el más ligero del conjunto de datos. Fuente
- LCP: Astro, aproximadamente 0,44 s, frente a WordPress, aproximadamente 0,81 s: aproximadamente un 46 % más rápido, según la comparación del informe. Cobertura
Registro de cambios
Actualizado el 11 ago 2026.
Resumen editorial y detalles registrados del cambio.Detalles del cambio
-
Los detalles del cambio están disponibles actualmente en inglés.
La comparación completa no está disponible: no se archivó una instantánea anterior para esta revisión.
Actualizado el 9 ago 2026.
Resumen editorial y detalles registrados del cambio.Detalles del cambio
-
Los detalles del cambio están disponibles actualmente en inglés.
La comparación completa no está disponible: no se archivó una instantánea anterior para esta revisión.
Actualizado el 17 jul 2026.
Resumen editorial y detalles registrados del cambio.Detalles del cambio
-
Los detalles del cambio están disponibles actualmente en inglés.
-
Los detalles del cambio están disponibles actualmente en inglés.
-
Los detalles del cambio están disponibles actualmente en inglés.
-
Los detalles del cambio están disponibles actualmente en inglés.
La comparación completa no está disponible: no se archivó una instantánea anterior para esta revisión.