Astro
The foundation for every website — ship HTML by default, hydrate an island only where a component genuinely needs client state.
Verified 2026-07-31 against docs.astro.build and astro.build/blog · Current: Astro 7.0, released 2026-06-22. Version facts go stale quickly — check the docs before quoting API detail.
Astro 7 is the foundation for every website. Content-led products — marketing, docs, editorial, brochure, blog — start here. Ship HTML by default; hydrate an island only where a component genuinely needs client state.
Astro is the answer whenever the product is pages. The full test — pages versus sessions, and what a site does when it grows a real app section — is on the stack index.
What 7.0 changed
Headline items from the 7.0 announcement (2026-06-22):
- Vite 8 underneath and a new Rust compiler — the release is framed around build speed.
- Advanced Routing, promoted from the 6.x experimental flag.
- Background dev server support and structured logging.
There is an official upgrade-to/v7 guide — read it before migrating a 6.x site
rather than guessing at breaking changes. Astro 6.0 landed March 2026, so the 6→7
gap is short: a project started before mid-2026 is likely on 6.x.
Structure
Astro's own conventions are the baseline — do not fight them:
src/
pages/ file-based routes; the URL map is readable from `ls`
layouts/ page shells
components/ .astro first; framework components only where they earn hydration
content/ content collections — type-safe, schema-validated
styles/Feature-based grouping still applies inside components/ and any non-trivial
logic: group by feature, not by widget type, and keep pure logic out of .astro
files so it stays testable.
Do not import a four-facade app architecture into a brochure site. A website's complexity is content modelling, not layering. The full rationale is on feature structure, and it applies where the complexity actually is.
Rules
- Content collections for anything repeated — posts, cases, people, docs. The schema is the contract; it catches a bad frontmatter key at build time instead of at render.
- Islands are opt-in and rare. Every
client:*directive is a decision to ship JavaScript. Default to zero; reach forclient:visibleorclient:idlebeforeclient:load. - Server islands for the personalised or slow fragment of an otherwise static page — that is the feature that keeps a page cacheable when one box needs live data.
- Pick the rendering mode per route, not per project: static where possible, on-demand where the content is genuinely dynamic.
- One adapter, chosen by the deploy target — decide it before writing routes, since it determines what on-demand rendering is available.
- Styling is Tailwind, same as everywhere. shadcn is a React component set — pull it in only inside a React island, never as a site-wide default.
Traps
- Reaching for a UI framework by reflex. A React island for something
.astrorenders fine costs a runtime, a hydration boundary and a bundle, for nothing. client:loadeverywhere → the JavaScript budget of an SPA with none of the benefits.- Fetching content at request time that could be a collection query at build time.
- Version drift. The 6→7 gap is about three months, so a snippet found online is often 6.x-shaped.