Perché abbiamo scelto Astro per il blog aziendale
Architettura a isole, zero JavaScript di default, Content Collections type-safe: cosa ci ha convinti dopo aver valutato Hugo, Eleventy e Next.js.
Quando abbiamo deciso di aprire questo blog, la domanda non era “se” usare un generatore di siti statici — su quello eravamo allineati — ma “quale”. Per due settimane abbiamo testato in parallelo quattro candidati: Hugo, Eleventy, Next.js (in modalità export statico) e Astro. Alla fine abbiamo scelto Astro. Ecco perché.
I criteri che contavano
Non cercavamo il “framework migliore” in assoluto, ma quello che minimizzava l’attrito per il nostro team specifico — sviluppatori abituati a TypeScript e JavaScript, con qualche bagaglio di Ruby — e che soddisfaceva tre requisiti non negoziabili: deploy su GitHub Pages, multilingua IT/EN e ricerca interna senza backend.
A questi tre si aggiungevano vincoli più morbidi ma sentiti: un design system custom moderno, performance impeccabili (è pur sempre il biglietto da visita di una software house), e una developer experience che non rallentasse la pubblicazione.
Perché non Hugo
Hugo è veloce. Tremendamente veloce. Compila 10.000 pagine in meno di 10 secondi, contro i 30-90 di Astro. Ma per un blog aziendale, anche con cento articoli ottimistici, parliamo di build da uno o due secondi in ogni caso: il vantaggio teorico evapora.
Quello che resta è il templating in Go. Un team JS/TS può imparare la sintassi {{ }} di Go in un pomeriggio, ma ogni volta che si vuole estendere un layout o costruire un componente leggermente più complesso si paga un costo di attrito. E i temi esistenti sono spesso scritti con assumption che ti vincolano molto.
Perché non Eleventy
Eleventy ci piaceva. È elegante, JavaScript-first, configurabile fino al midollo. Ma è anche un framework “do it yourself”: per arrivare al livello di Astro su tipi sicuri (schema su frontmatter via Zod), routing i18n nativo e immagini ottimizzate, dovevamo assemblare noi i pezzi con plugin di comunità o codice custom.
Per un singolo sviluppatore che vuole il massimo controllo, è la scelta giusta. Per un team che deve mantenerlo nel tempo, ogni plugin aggiunto è una potenziale superficie di debito.
Perché non Next.js
Next.js sarebbe stato un esercizio di overkill: avremmo importato l’intero modello di rendering ibrido (SSR, ISR, client components) per generare HTML statico. Il bundle finale, anche dopo l’export, porta con sé runtime che non ci serve. E configurare i18n statico in Next con i nuovi App Router è ancora un esercizio fragile.
Cosa ha vinto Astro
Sette cose, in ordine di importanza.
Le Content Collections. Definire uno schema Zod per il frontmatter degli articoli ci ha dato autocomplete in editor, validazione a build-time e zero possibilità di pubblicare un post con il tag frontned invece di frontend. Per chi ha sofferto di typo in dieci anni di repository, questo da solo vale l’adozione.
const blog = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/data/blog" }),
schema: ({ image }) => z.object({
title: z.string().max(120),
pubDate: z.coerce.date(),
tags: z.array(z.string()).default([]),
cover: image().optional(),
}),
});
I tipi corrispondenti vengono generati automaticamente in .astro/types.d.ts ad ogni dev/build: getCollection('blog') ti restituisce oggetti già tipizzati, senza scrivere una sola .d.ts a mano e senza disallineamenti tra schema e codice consumatore.
L’i18n nativo. Dal 4.0 Astro ha un’API i18n nel core: configuri locales, defaultLocale, una strategia di fallback, e ottieni helper come getRelativeLocaleUrl() e Astro.currentLocale. Niente plugin di terzi, niente convenzioni di routing magiche.
Le isole. L’architettura a isole è il differenziale tecnico più interessante: la pagina è HTML statico, e i componenti interattivi (selettore lingua, toggle tema, eventuale ricerca live) sono “isole” che si idratano indipendentemente. Su questa stessa pagina, il JavaScript inviato al browser è meno di 5 KB — la maggior parte è del language switcher.
Due dettagli che pesano nella pratica:
- Le isole sono framework-agnostic: nella stessa pagina puoi mescolare React, Vue, Svelte, Solid, Preact. Per un team multi-stack è la garanzia di non doversi vincolare a un linguaggio a priori — quando avremo un’isola particolarmente complessa, useremo lo strumento adatto a quel pezzo, non quello che il framework ci impone.
- Hai controllo granulare su quando ogni isola si idrata:
client:load(subito),client:visible(quando entra in viewport),client:idle(quando il main thread è libero),client:media="(max-width: 768px)"(solo a quella media query). Il toggle tema del nostro Header èclient:loadperché va attivo prima del primo paint; un eventuale form a fondo pagina sarebbeclient:visible.
Il formato .astro. Un file .astro è la cosa più simile a “JSX server-only” che abbiamo trovato. In cima un blocco TypeScript per la logica di fetching e rendering, sotto un template HTML, in fondo opzionalmente CSS che viene automaticamente scoped al componente. Niente JavaScript inviato al browser, a meno che non lo decidiamo esplicitamente. Esempio semplificato:
---
import { getLangFromUrl } from "@/i18n/utils";
const lang = getLangFromUrl(Astro.url);
---
<nav>
<a href={`/${lang}/blog`}>Blog</a>
</nav>
<style>
nav { display: flex; gap: 1rem; }
</style>
Il <style> è automaticamente scoped: niente nomi di classe paranoici, niente CSS Modules, niente styled-components. Per un team che vuole il controllo del CSS senza la trappola della cascade globale è esattamente il bilancio giusto.
MDX, quando il Markdown non basta. La maggior parte degli articoli sono .md puro: testo, code block, link. Quando serve qualcosa in più — una callout custom, un grafico interattivo, un confronto side-by-side fra due snippet — basta rinominare il file in .mdx e si possono importare componenti Astro (o React/Vue/Svelte se ne hai bisogno come isole) e usarli inline col resto della prosa:
---
title: "Protocolli di campo nell'IoT"
pubDate: 2026-04-12
---
import Callout from "@/components/Callout.astro";
import LatencyChart from "@/components/charts/LatencyChart.astro";
L'industria ha tre protocolli di campo dominanti — Modbus, OPC UA, MQTT.
<Callout type="warning">
Modbus non offre autenticazione: va sempre incapsulato in TLS o VPN.
</Callout>
<LatencyChart data={[{p: "Modbus", ms: 12}, {p: "OPC UA", ms: 8}]} />
Tre vantaggi concreti rispetto al Markdown puro:
- Componenti riutilizzabili invece di copia-incolla di blocchi HTML. La callout sopra è un file
.astrosolo da scrivere una volta. - Stessi tipi del resto del progetto: il componente importato ha le sue props tipizzate, quindi un errore nello use del componente lo prende l’editor a tempo di scrittura, non un lettore a runtime.
- Lo schema Zod del frontmatter resta identico e l’auto rendering pure: non c’è una sintassi parallela come gli shortcode di Hugo o gli include di Eleventy. Per gli articoli che restano Markdown puro non c’è nessun costo: paghi MDX solo dove lo usi.
L’unica accortezza è non abusarne. Se ogni articolo richiede dieci import custom, il valore della prosa scivola dietro al boilerplate: MDX è uno strumento per i casi in cui il Markdown non basta, non un sostituto.
Le immagini come cittadini di prima classe. <Image /> e getImage() fanno automaticamente resize, conversione in WebP/AVIF e generano srcset per la responsive delivery. Soprattutto: lo schema Zod accetta image() come tipo di campo (vedi cover nello snippet sopra), quindi quando dichiari una cover nel frontmatter di un articolo, Astro la importa, la valida, la ottimizza e ti restituisce un oggetto già processato a build-time. Hugo richiede plugin per arrivare a un risultato simile, Eleventy ti fa scrivere shortcode, Next richiede next/image con vincoli di hosting che ti incatenano a Vercel se vuoi l’ottimizzazione on-the-fly.
View Transitions, senza diventare una SPA. Da Astro 4 c’è <ClientRouter />, un componente che usa l’API nativa View Transitions del browser per fare navigation client-side tra pagine statiche. Risultato: la sensazione di una SPA (niente flash bianco al click) senza i costi di una SPA — niente bundle JS gigante, niente perdita di state condiviso, niente SEO da sistemare. Non lo stiamo ancora usando in questo blog, ma è una direzione di crescita gratis che gli altri candidati non offrono.
“Astro feels more like a complete web framework, offering features like file-based routing, content collections with type safety, and built-in image optimization.”
I trade-off che ci siamo presi
Nessuna scelta è gratis. Quello che abbiamo perso scegliendo Astro rispetto ad alternative:
- Build time rispetto a Hugo, se un giorno avremo migliaia di articoli. Non è un problema oggi.
- Ecosistema di plugin rispetto a Next.js. Astro cresce in fretta ma non ha la stessa massa critica.
- Familiarità per chi viene da WordPress o Wix. Ma su questo nessuno dei candidati aiutava.
Prossimi passi
Nei prossimi articoli racconteremo l’integrazione con Pagefind per la ricerca client-side, come abbiamo modellato l’i18n con translationKey per legare articoli equivalenti tra lingue, e il workflow di deploy su GitHub Pages. Stay tuned.