Astro
Pathrule3 Rules • 3 Memories • 1 Skill
A pattern bundle for Astro 5 projects built around islands architecture, the Content Layer API, and server islands. It keeps agents disciplined about partial hydration, schema-validated content, and the static-first render model so pages stay fast and predictable. Use it for content-driven sites, marketing pages, docs, and blogs that mix static output with a few interactive islands.
Suggested path map
Pathrule places each piece on the matching path, so your assistant only sees it where it belongs. This is the scoping you get on import; you can adjust it in your workspace.
Rules
3Hydrate islands intentionally, never by reflex/src/componentshighadvisoryUI framework components stay static HTML unless a client:* directive proves they must be interactive, and then use the lightest one.
| 1 | Astro renders UI framework components (React, Vue, Svelte, Solid, Preact) to static HTML by default and ships zero JavaScript for them. A `client:*` directive is a performance contract, not boilerplate. Default to no directive and add the lightest one only when interaction is genuinely required. |
| 2 | |
| 3 | - `client:load` is high priority: hydrates immediately on page load. Reserve it for above-the-fold controls that must work the instant the page paints. |
| 4 | - `client:idle` is medium priority: hydrates after the page finishes loading via `requestIdleCallback`. Pass `client:idle={{ timeout: 500 }}` to cap how long it may wait. |
| 5 | - `client:visible` is low priority: hydrates when the element scrolls into view via `IntersectionObserver`. For heavy below-the-fold components pass `client:visible={{ rootMargin: "200px" }}` so they hydrate just before they appear and avoid layout shift. |
| 6 | - `client:media="(max-width: 50em)"` hydrates only when the media query matches; use it for controls that only exist at certain breakpoints. |
| 7 | - Treat `client:only="react"` as a last resort. It skips server rendering entirely, which hurts SEO and removes the static HTML fallback. Provide a `slot="fallback"` when you must use it. |
| 8 | - Split large interactive components so only the truly dynamic part hydrates and the surrounding markup stays static `.astro` output. |
Every build-time collection needs a loader and a Zod schema/src/contenthighstrictBuild-time content is declared in src/content.config.ts with an explicit loader plus a Zod schema, and queried only through getCollection/getEntry.
| 1 | Astro's legacy content collections API was removed in Astro 6. All build-time collections use the Content Layer API, declared in `src/content.config.ts` with an explicit `loader` and a Zod `schema` so frontmatter is validated at build time and queries are fully typed. |
| 2 | |
| 3 | - Import `z` from `astro/zod` and the loaders from `astro/loaders`. Astro 6 bundles Zod v4, so use the v4 API for custom refinements and error maps. |
| 4 | - Use the built-in `glob()` loader for a directory of Markdown, MDX, JSON, YAML, or TOML files, and `file()` to load many entries from a single local file. Point them at a `base` directory and a `pattern`. |
| 5 | - Use a custom or community loader for CMS, API, or database sources that are known at build time. |
| 6 | - Always declare a `schema`. It makes `getCollection()` and `getEntry()` return typed, validated data and makes bad frontmatter fail the build instead of leaking to runtime. |
| 7 | - Link collections to each other with the `reference()` helper rather than hardcoding ids. |
| 8 | - Query content only through `getCollection()` / `getEntry()` from `astro:content`, and render Markdown bodies through the entry's `render()`. Never read collection files with `fs` or a glob import. |
Do not use APIs removed in Astro 6/srchighstrictAstro.glob(), the ViewTransitions component, emitESMImage(), and the legacy src/content/config.ts no longer exist.
| 1 | Astro 6 removed several long-deprecated APIs. Using them silently breaks the build or behaves unexpectedly, and agents trained on older Astro frequently reach for them. |
| 2 | |
| 3 | - `Astro.glob()` is removed. Use Vite's `import.meta.glob()` for arbitrary files, and `getCollection()` for content collections. |
| 4 | - The `<ViewTransitions />` component is removed. Use `<ClientRouter />` from `astro:transitions` instead. Also drop the `handleForms` prop if you carried it over; form handling is on by default. |
| 5 | - `emitESMImage()` is removed from the image pipeline. |
| 6 | - The content config no longer lives at `src/content/config.ts`. It must be `src/content.config.ts` at the `src` root, and config files cannot be `.cjs` or `.cts`. |
| 7 | - Astro 6 requires Node 22.12.0 or newer and runs on Vite 7. Do not pin Node 18 or 20 in CI or engines. |
Memories
3Rendering model: static by default, server islands for the dynamic bits/src/pagesKeep pages prerendered and isolate personalized fragments into server:defer islands instead of making whole routes dynamic.
| 1 | Astro pages are statically prerendered by default. Keep them that way so the page shell can be cached aggressively, and push only the per-request parts to their own server-rendered islands. |
| 2 | |
| 3 | - Mark personalized or per-request fragments (avatar, cart count, recommendations, A/B variant) with `server:defer` so each renders in its own request without blocking the cached page. The island is effectively a serverless function that returns HTML. |
| 4 | - Give every server island a `slot="fallback"`. The fallback ships in the initial HTML and is swapped for the real content once the island resolves, so users never see an empty hole. |
| 5 | - Reach for full on-demand SSR (`export const prerender = false`) only when an entire route is dynamic. On an otherwise-static page, prefer one or more server islands over making the whole route dynamic. |
| 6 | - Server islands and SSR routes both require an SSR adapter (Node, Netlify, Vercel, Cloudflare) configured in `astro.config`, even when the rest of the site is static. There is no adapter needed in `astro dev`, so this gap only surfaces at deploy time. |
Build-time collections vs live collections: pick the right one/src/contentsrc/content.config.ts is for content known at build; src/live.config.ts (new in Astro 6) is for data fetched per request.
| 1 | Astro 6 added Live Content Collections alongside the existing build-time collections. They share the content layer mental model but are separate APIs with separate config files, and mixing them up is the most common new-in-6 mistake. |
| 2 | |
| 3 | - Build-time collections live in `src/content.config.ts`, are validated and frozen at build, and are queried with `getCollection()` / `getEntry()`. Use them for blog posts, docs, marketing copy, anything that can be baked into the deploy. |
| 4 | - Live collections live in a separate `src/live.config.ts`, fetch at request time, and are queried with `getLiveCollection()` / `getLiveEntry()` from `astro:content`. Use them for inventory, prices, feeds, scores, anything that must be fresh on every request. |
| 5 | - There are no built-in live loaders. A live loader is a custom object with a `name`, a `loadCollection` method returning an array, and a `loadEntry` method returning one item. This is different from the build-time loader's single `load` method. |
| 6 | - Live collections run per request, so a route that uses one is dynamic and needs an SSR adapter. Do not default to live collections for content that rarely changes; the build-time path is faster and cacheable. |
| 7 | |
| 8 | See /src/pages for how dynamic data interacts with the static-first rendering model. |
Skills
1astro-review/rootPre-merge checklist for Astro 6 pages, islands, content collections, and view transitions.
| 1 | --- |
| 2 | name: astro-review |
| 3 | description: Review checklist for Astro 6 work covering hydration directives, the Content Layer API, build-time vs live collections, server islands, rendering mode, removed APIs, and view transitions before merging. |
| 4 | --- |
| 5 | |
| 6 | # Astro review |
| 7 | |
| 8 | ## Hydration and shipped JavaScript |
| 9 | - [ ] Framework components render static HTML by default; every `client:*` directive is justified and uses the lightest option (`visible`/`idle`/`media` over `load`). |
| 10 | - [ ] Heavy `client:visible` components pass a `rootMargin` to hydrate just before they appear. |
| 11 | - [ ] No stray `client:only` that drops server rendering and the static fallback; where used, a `slot="fallback"` exists. |
| 12 | - [ ] No unnecessary JavaScript ships; the page works with scripts disabled where it reasonably should. |
| 13 | |
| 14 | ## Content collections |
| 15 | - [ ] Build-time content is declared in `src/content.config.ts` with an explicit `loader` and a Zod `schema` (Zod v4 API, `z` from `astro/zod`). |
| 16 | - [ ] Content is read through `getCollection()` / `getEntry()`, never raw `fs`, `import.meta.glob`, or the removed `Astro.glob()`. |
| 17 | - [ ] Cross-collection links use `reference()`. |
| 18 | - [ ] Live data uses `src/live.config.ts` + `getLiveCollection()` / `getLiveEntry()`, not a build-time collection; rarely-changing content stays build-time. |
| 19 | |
| 20 | ## Rendering and deployment |
| 21 | - [ ] Pages stay prerendered by default; `prerender = false` is used only for fully dynamic routes. |
| 22 | - [ ] Personalized fragments use `server:defer` with a `slot="fallback"`. |
| 23 | - [ ] An SSR adapter is configured if any route uses SSR, a server island, or a live collection (works in dev without one, fails at deploy). |
| 24 | |
| 25 | ## Astro 6 removed APIs and view transitions |
| 26 | - [ ] No `Astro.glob()`, no `<ViewTransitions />`, no `emitESMImage()`, no `src/content/config.ts`, no `.cjs`/`.cts` config. |
| 27 | - [ ] Node engine is 22.12.0+; project builds on Vite 7. |
| 28 | - [ ] View Transitions go through `<ClientRouter />`; `transition:persist` and `transition:name` are applied where state or motion continuity matters. |
| 29 | - [ ] Navigation-dependent scripts listen for `astro:page-load`, and animations respect `prefers-reduced-motion`. |
Why this pattern
Agents reach for client-side hydration and unvalidated content by default, bloating Astro pages with JavaScript and runtime errors.
Built for Teams building content-driven Astro sites: marketing pages, docs, blogs, and commerce fronts..
Keeps your assistant from:
- Slapping client:load on every interactive component and shipping needless JavaScript
- Reading content with raw fs or import.meta.glob instead of schema-validated content collections
- Blocking the whole page on a slow personalized request instead of deferring it to a server island
- License
- Apache-2.0
- Version
- 1.0.0
- Updated
- 2026-06-09