SEO per Astro

Come ottimizzare Astro per la SEO: HTML statico rispetto a rendering server, meta tag, sitemap, canonical, Content Collections, immagini, Server Islands e View Transitions.

Prima pubblicazione: 26 giu 2026 · Ultimo aggiornamento: 11 ago 2026 · Advanced
Lingue

Astro è un’ottima scelta per la SEO perché per impostazione predefinita costruisce le pagine come HTML statico prima che arrivi il crawler: non c’è un’ondata di rendering JavaScript da aspettare per le route prerenderizzate. Le isole idratano solo i componenti marcati con client:*, mentre client:only non produce HTML server; le Server Islands richiedono un adapter e servono il fallback nel documento iniziale. Astro però non genera automaticamente meta tag, canonical, sitemap, dati strutturati o robots.txt: configurali esplicitamente e verifica le route distribuite, perché nessuna architettura garantisce da sola scansionabilità, indicizzazione, ranking o Core Web Vitals. Le View Transitions usano history.pushState e sono sicure per la SEO.

TL;DR — Astro è architetturalmente ben predisposto per la SEO: per impostazione predefinita pagine ed endpoint vengono prerenderizzati in HTML statico, quindi per quel contenuto non c’è un’ondata di coda di rendering da aspettare; ma è un’impostazione predefinita, non una garanzia universale, e HTML statico/server da solo non dimostra scansionabilità, indicizzazione, ranking o Core Web Vitals per i tuoi URL in produzione. L’architettura a isole idrata solo i componenti che contrassegni con una direttiva client:*: tutto il resto distribuisce HTML senza il proprio JavaScript di hydration, anche se gli script della pagina, altre isole e i miglioramenti del router possono aggiungere JavaScript altrove nella pagina. Astro non genera automaticamente meta tag, canonical, sitemap o dati strutturati: collegali esplicitamente, idealmente validandoli tramite Content Collections + Zod. Le Server Islands (che richiedono un adapter) servono il guscio statico con contenuto di fallback nel documento iniziale e recuperano il contenuto differito in modo indipendente dopo: verifica cosa recupera davvero un determinato crawler invece di darlo per scontato. Le View Transitions usano history.pushState e sono sicure per la SEO; Google scansiona normalmente le pagine MPA sottostanti. Gestisco patrickstox.com con Astro e le funzionalità sotto sono quelle che uso davvero, validate sul sito distribuito, non solo nello sviluppo locale.

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

Perché Astro evita del tutto il problema del rendering JavaScript

Il motivo per cui la SEO JavaScript è difficile è la seconda ondata. Google recupera prima l’HTML grezzo, poi accoda la pagina per il rendering successivo in Chromium headless: ed è quella coda il rischio. La documentazione di Google lo descrive così: “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.” (traduzione) «Googlebot mette in coda per il rendering tutte le pagine con stato HTTP 200, a meno che un meta tag robots non dica a Google di non indicizzare la pagina. La pagina può restare in questa coda per pochi secondi, ma può volerci più tempo». Per una SPA renderizzata dal client, il contenuto non esiste finché non viene eseguita quell’ondata di rendering.

La modalità di output predefinita di Astro è statica: pagine ed endpoint vengono prerenderizzati in un file HTML completo al momento della build. Quindi, per una route che usa questa modalità predefinita, l’HTML grezzo è la pagina renderizzata. 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 Non c’è una seconda ondata da aspettare per quella route, perché non resta nulla da eseguire. Googlebot vede il contenuto completo al primo fetch. Come dice Joost de Valk (fondatore di Yoast), “From an SEO perspective, static HTML on a CDN is a better starting point than most CMSes will ever give you.” (traduzione) «Dal punto di vista SEO, l’HTML statico su una CDN è un punto di partenza migliore di quello che la maggior parte dei CMS potrà mai offrirti».

Questa è però la modalità predefinita, non una proprietà universale di ogni route. Imposta output: 'server' e la modalità predefinita passa al rendering on demand (ne parleremo sotto); anche in un progetto con predefinito statico, un adapter permette a una singola route di rinunciare al prerendering con export const prerender = false. Nulla di tutto questo è garantito dalla sola architettura: HTML statico o server, isole e adapter non garantiscono da soli scansionabilità, indicizzazione, ranking o Core Web Vitals. Dipendono dalla route distribuita e dal crawler specifico, quindi verificali invece di presumere che sia il framework a gestirli.

Questo aiuta anche con i crawler che non possono fare rendering. Google nota chiaramente che “not all bots can run JavaScript” (traduzione) «non tutti i bot possono eseguire JavaScript» — ed è la realtà del 2026 per la maggior parte dei crawler AI e molti strumenti di terze parti. L’output HTML-first di Astro è leggibile da ognuno di loro quando è davvero prerenderizzato, non soltanto da Googlebot. (È lo stesso punto che sostengo in SEO per un CMS headless: la modalità di rendering è il prodotto.)

Architettura a isole: JavaScript solo dove lo chiedi

Astro renderizza i tuoi componenti in HTML e, per usare le sue parole, distribuisce “just HTML & CSS, stripping out all client-side JavaScript automatically.” (traduzione) «solo HTML e CSS, eliminando automaticamente tutto il JavaScript lato client». L’interattività è opt-in. Contrassegni un componente con una direttiva client:*client:load, client:idle o client:visible — e solo quell’isola viene idratata con JavaScript. Tutto il resto rimane HTML statico. 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

Per la SEO è quasi ideale. Il contenuto che Googlebot deve indicizzare è semplice HTML e i widget interattivi non lo trascinano verso il basso. client:visible è particolarmente utile: un componente sotto la piega non inizia nemmeno a idratarsi finché non entra nella viewport, quindi non blocca mai il tuo LCP. Il concetto viene da Jason Miller (creatore di Preact), che ha descritto “rendering HTML pages on the server, and inject[ing] placeholders or slots around highly dynamic regions” (traduzione) «renderizzare pagine HTML sul server e iniettare placeholder o slot attorno a regioni altamente dinamiche» per l’hydration selettiva.

Due sfumature richiedono precisione, perché i contenuti dei concorrenti tendono a confonderle:

  • client:only è un’altra cosa. A differenza di client:load/client:idle/client:visible, un componente client:only salta interamente il rendering server: sul server non produce HTML. Qualsiasi contenuto indicizzabile collocato solo dentro un componente client:only non è nel documento recuperato da Googlebot; esiste solo dopo che il browser lo idrata. Non mettere lì il contenuto principale.
  • Questa è hydration selettiva, non resumability. Astro riesegue da zero nel browser il codice client di ogni isola; non riprende uno stato di esecuzione serializzato sul server come fa un modello di resumability (quello di Qwik, per esempio). Nei contenuti scritti le due cose vengono confuse: non sono lo stesso meccanismo.
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

E un componente non idratato non esaurisce il quadro JavaScript della pagina. «Zero JS» descrive un componente senza una direttiva client:*: Astro può comunque distribuire tag <script> a livello di pagina, il router View Transitions e altre isole altrove nella stessa pagina. Descrivi ciò che viene distribuito per componente/route, non fare un’affermazione assoluta sulla pagina.

Che cosa Astro NON fa automaticamente

Astro genera HTML semantico pulito — e, per la SEO, nient’altro. Non ci sono metadati, canonical, sitemap o dati strutturati pronti all’uso. Il mito che «Astro sia automaticamente ottimizzato per la SEO» è proprio questo: un mito. Sono responsabilità tue:

  • Meta tag (title, description, Open Graph, Twitter)
  • URL canonical
  • La sitemap (tramite l’integrazione ufficiale)
  • Dati strutturati / JSON-LD
  • robots.txt

Astro è la base migliore che abbia usato, ma è una base, non una casa finita.

La sitemap: @astrojs/sitemap

Installala con npx astro add sitemap. Esegue il crawling delle route generate staticamente ed emette una sitemap-index.xml più file sitemap-0.xml suddivisi in blocchi al momento della build. Due cose causano problemi: 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

  • Devi impostare site: in astro.config.mjs. Senza, l’integrazione non genera nulla in silenzio. È la causa più comune del «dov’è la mia sitemap?».
  • Devi aggiungere tu la riga della sitemap a robots.txt. Astro non lo fa.

Per avere controllo, filter() esclude le route (pagine preview/draft — è esattamente ciò per cui lo uso su questo sito), serialize() permette di impostare lastmod/changefreq/priority e l’opzione i18n emette voci hreflang nella sitemap. È ciò che specifica la documentazione attuale di @astrojs/sitemap: se usi una release più vecchia, verifica la versione installata, perché il comportamento dell’integrazione è già cambiato tra major version.

L’ambito che trae in inganno: l’integrazione scopre le route generate staticamente. Se alcuni URL esistono solo a runtime — route renderizzate server (output: 'server') o generate on demand invece che al momento della build — non dare per scontato che siano nella sitemap. Aggiungili esplicitamente con customPages, poi apri davvero sitemap-index.xml dopo una build per confermare che ci siano. Non fidarti dell’idea che «l’integrazione gestisca tutto» per una route statica che non è di build time.

Meta tag e canonical: il pattern BaseLayout

Astro non ha uno speciale componente <Head>: controlli direttamente <head> nei file .astro. Il pattern standard (e quello che uso io) è un unico BaseLayout.astro che riceve title, description e canonicalURL come props e scrive l’head. Imposta il canonical esplicitamente su ogni pagina e mantienilo coerente con og:url. Non ti serve una libreria, ma il pacchetto community astro-seo (npm) è un comodo wrapper a componente unico per title/description/OG/Twitter/canonical, se lo desideri.

Content Collections come rete di sicurezza SEO

Questa è la funzionalità SEO sottovalutata di Astro. Le Content Collections sono un livello di contenuti type-safe per Markdown/MDX/JSON, con validazione dello schema Zod. Questo significa che puoi rendere obbligatori title e description: se una pagina ne manca uno, la build fallisce. Non puoi distribuire per errore una pagina senza title. Le funzioni di query (getCollection(), getEntry()) generano pagine statiche al momento della build, quindi l’output è semplice HTML quando viene distribuito. E poiché MDX conserva il markdown grezzo come fonte di verità, quei file sono anche contenuti sorgente puliti per i crawler AI e i pattern in stile llms.txt. Questo stesso sito è costruito con Content Collections e frontmatter validato da Zod.

astro:assets: immagini fatte bene (con una trappola)

Il componente <Image /> converte automaticamente in WebP, deduce le dimensioni per “avoid Cumulative Layout Shift (CLS),” (traduzione) «evitare il Cumulative Layout Shift (CLS)», imposta loading="lazy" per impostazione predefinita e richiede alt: un alt mancante è un errore di compilazione. <Picture /> estende il comportamento con elementi <source> AVIF/WebP/fallback.

La trappola è che il loading="lazy" automatico è sbagliato per la tua immagine LCP (di solito l’hero). Il caricamento lazy dell’immagine più importante la ritarda. Per le immagini above-the-fold, sostituiscilo con loading="eager" e fetchpriority="high". Le immagini remote richiedono width e height espliciti.

Server Islands: cosa vedono davvero i crawler

Le Server Islands (Astro 4.12+) sono la funzionalità che la maggior parte delle guide concorrenti sbaglia. Con server:defer, un componente viene renderizzato sul server indipendentemente dalla pagina principale. Il guscio statico viene servito subito; secondo la documentazione di 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.” (traduzione) «La pagina viene renderizzata immediatamente con l’eventuale contenuto di fallback specificato come segnaposto. Poi i contenuti del componente vengono recuperati sul client e mostrati quando disponibili».

Due cose richiedono precisione. Primo, le Server Islands richiedono un adapter: sono una funzionalità on demand, non qualcosa che una build completamente statica produca da sola. Secondo, la sequenza è questa: il documento iniziale viene distribuito con il contenuto di fallback configurato e il contenuto reale dell’isola viene recuperato con una richiesta separata e indipendente dopo il caricamento della pagina, tramite un proprio endpoint. Questo stabilisce un limite netto per ciò che contiene il primo documento: non generalizzerei oltre su ciò che ogni crawler specifico recupera dopo, senza testare direttamente i tuoi URL distribuiti.

La conseguenza SEO è concreta: l’HTML statico che un crawler legge al primo fetch contiene il contenuto di fallback, non quello dell’isola differita. È perfetto per ciò a cui servono le Server Islands — dati personalizzati e specifici della sessione (stato di accesso, conteggio del carrello, raccomandazioni) che non dovrebbero comunque essere messi in cache o indicizzati. È sbagliato per il contenuto principale indicizzabile. Metti tutto ciò che deve posizionarsi nel template principale Astro e lascia alle Server Islands i dettagli dinamici che lo circondano.

Modalità di output: statico rispetto a server e override per route

La modalità di output predefinita di Astro è static: pagine ed endpoint vengono prerenderizzati in HTML al momento della build. Imposta output: 'server' in astro.config.mjs e la modalità predefinita passa al rendering on demand: le pagine vengono renderizzate per richiesta (con un adapter), utile per autenticazione, dati in tempo reale o personalizzazione oltre ciò che coprono le Server Islands. In entrambi i casi puoi sostituire la modalità predefinita per route: in un progetto con predefinito statico, export const prerender = false abilita il rendering on demand; in un progetto con predefinito server, export const prerender = true riporta una route al prerendering durante la build. Quindi «il mio sito è statico» o «il mio sito è SSR» raramente è vero per ogni route: controlla l’impostazione per route, non solo la configurazione al livello superiore.

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

Dal punto di vista della sola SEO, HTML prerenderizzato e HTML on demand sono equivalenti: entrambi consegnano HTML completo al primo fetch del crawler, dopo che hai effettivamente verificato che la route restituisca 200 con markup completo. Le route on demand possono trasmettere l’HTML in streaming e dati lenti o condizioni di rete possono ritardare blocchi successivi, quindi una risposta in streaming non dimostra automaticamente che ogni parte del contenuto sia arrivata: controlla, non presumere. La differenza reale tra le due modalità è operativa: il contenuto prerenderizzato resta fisso fino alla build successiva (o a un refresh runtime configurato separatamente) e viene servito direttamente dal bordo CDN; il contenuto on demand è sempre aggiornato, ma dipende dall’operatività corretta dell’adapter e del runtime in produzione. Non trattarla come una decisione SEO: scegli in base alla freschezza dei dati e alle operazioni, poi valida route distribuite, status, redirect e header della risposta invece di estrapolare da ciò che ha funzionato nello sviluppo locale.

View Transitions: sicure per la SEO, nonostante l’aspetto da SPA

<ClientRouter /> di Astro (in precedenza <ViewTransitions />) offre una navigazione morbida simile a una SPA usando l’API View Transitions del browser e la History API. Il fatto decisivo è che naviga con history.pushState, esattamente ciò che Google raccomanda per la navigazione lato client: Google avverte che gli URL basati su frammenti (#hash) sono qualcosa che “can’t reliably resolve” (traduzione) «non riesce a risolvere in modo affidabile». Soprattutto, le View Transitions sono un miglioramento lato browser. Quando Googlebot scansiona, richiede ogni URL e riceve una normale pagina HTML completa: la MPA sottostante non viene toccata. Le transizioni modificano solo ciò che una persona vede nel browser.

Quindi no, le View Transitions non trasformano il tuo sito Astro in una SPA e non rompono la SEO. Una lacuna da tenere presente è che la documentazione Astro sulle View Transitions non ha una sezione SEO, probabilmente per questo persiste il mito «rompe la SEO». Per verificare il tuo sito, recupera direttamente alcuni URL e conferma che ciascuno restituisca HTML completo: non fidarti, controlla la tua distribuzione.

Errori SEO comuni in Astro

  1. Presumere che Astro gestisca la SEO per te. Gestisce l’HTML. Meta, canonical, sitemap e schema sono responsabilità tue.
  2. Dimenticare site: nella configurazione: la sitemap non viene generata e non lo segnala.
  3. Non aggiungere la sitemap a robots.txt: Astro non lo fa.
  4. Caricare lazy l’immagine LCP: sostituisci il caricamento dell’hero con eager + fetchpriority.
  5. Mettere contenuto indicizzabile in una Server Island: i crawler vedono il fallback, non il contenuto, e le Server Islands richiedono comunque un adapter.
  6. Inseguire un punteggio Lighthouse perfetto e fermarsi lì. La velocità è un segnale di ranking, non il segnale di ranking. Una pagina vuota veloce non si posiziona: contenuto, link ed E-E-A-T fanno ancora il lavoro principale.
  7. Mettere contenuto indicizzabile solo in un componente client:only. A differenza delle altre direttive client:*, client:only salta completamente il rendering server: per quel componente non c’è HTML finché il browser non lo idrata.
  8. Trattare «Astro è statico/veloce» come una garanzia del risultato. HTML statico o on demand, isole e adapter sono meccanismi: non garantiscono da soli scansionabilità, indicizzazione, ranking o Core Web Vitals. Valida la route distribuita, non il diagramma dell’architettura.

Dove si colloca nel cluster

Astro è una risposta specifica e insolitamente favorevole alla SEO alle domande che JavaScript SEO solleva sul rendering, oltre a essere un frontend popolare per le configurazioni di CMS headless. Il lato prestazionale si collega direttamente ai Core Web Vitals nel cluster delle prestazioni web e la disciplina di test «il mio contenuto è davvero nell’HTML?» è la stessa dei cluster crawling e indicizzazione.

Add an expert note

Pin an expert quote

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