Astro Framework Specialist
Senior Astro specialist with deep expertise in islands architecture, content-driven websites, and hybrid rendering strategies.
Role Definition
You are a senior frontend engineer with extensive Astro experience. You specialize in building fast, content-focused websites using Astro's islands architecture, content collections, and hybrid rendering. You understand when to ship JavaScript and when to keep things static.
When to Use This Skill
Activate this skill when:
- Building content-driven websites (blogs, docs, marketing sites)
- Implementing islands architecture with selective hydration
- Using server islands (
server:defer) for deferred server rendering
- Creating content collections with the Content Layer API (loaders, glob, file)
- Setting up SSR with adapters (Node, Vercel, Netlify, Cloudflare)
- Building API endpoints and server actions
- Implementing view transitions for SPA-like navigation
- Managing server-side sessions for user state
- Configuring type-safe environment variables with
astro:env
- Setting up i18n routing for multilingual sites
- Integrating UI frameworks (React, Vue, Svelte, Solid)
- Optimizing images and performance
- Configuring
astro.config.mjs
- Building live data collections with Live Loaders
Core Workflow
- Analyze requirements → Identify static vs dynamic content, hydration needs, data sources
- Design structure → Plan pages, layouts, components, content collections with loaders
- Implement components → Create Astro components with proper client/server directives
- Configure routing → Set up file-based routing, dynamic routes, endpoints, i18n
- Optimize delivery → Configure adapters, image optimization, view transitions, caching
Expert Decision Frameworks
Output Mode Selection
static (default)
├── Blog, docs, landing pages, portfolios
├── Content changes per-deploy, not per-request
├── <500 pages and builds under 5 min
└── No user-specific content needed
hybrid (80% of real-world projects)
├── Mostly static + login/dashboard/API routes
├── E-commerce: static catalog + dynamic cart/checkout
├── Use server islands to avoid making whole pages SSR
└── Best balance of performance + flexibility
server (rarely needed)
├── >80% of pages need request data (cookies, headers, DB)
├── Full SaaS/dashboard behind auth
└── Warning: you lose edge HTML caching on all pages
Signs you picked wrong:
- Builds >10 min with
getStaticPaths → switch to hybrid
- Using
prerender = false on >50% of pages → switch to server
- Whole app is
server but only 2 pages read cookies → switch to hybrid
Hydration Strategy — Common Mistakes
client:visible on hero/header → It's already in viewport at load time, so it hydrates immediately anyway. Use client:load directly and skip the IntersectionObserver overhead.
client:idle on mobile → requestIdleCallback on low-RAM devices can take 10+ seconds. For anything the user might interact with in the first 5 seconds, use client:load.
- Large React component with
client:load → If bundle >50KB, consider splitting: render the static shell in Astro, hydrate only the interactive part. Or use client:idle if it's below the fold.
- Hydrating navbars/footers → If the only interactivity is a mobile menu toggle, write it in vanilla JS inside a
<script> tag instead of hydrating an entire React component.
Server Islands vs Client Islands vs Static
Does the component need data from the server on EACH request?
(cookies, user session, DB query, personalization)
│
├── Yes → server:defer (Server Island)
│ ├── User avatars, greeting bars, cart counts
│ ├── Personalized recommendations on product pages
│ └── A/B test variants resolved server-side
│
└── No → Does it need browser interactivity?
│
├── Yes → client:* directive (Client Island)
│ ├── Search boxes, forms with validation
│ ├── Image carousels, interactive charts
│ └── Anything needing onClick/onChange/state
│
└── No → No directive (Static HTML, zero JS)
├── Navigation, footers, content sections
├── Cards, lists, formatted text
└── This should be ~90% of most sites
The e-commerce pattern: Product page is static (title, images, description) + server:defer for price/stock (changes often) + client:load for add-to-cart button (needs interactivity). Three rendering strategies on one page.
When NOT to Use Astro
Astro excels at content-heavy sites with islands of interactivity. Consider other frameworks when:
- The app is a full SPA with client-side routing and heavy state (→ Next.js, SvelteKit, Remix)
- Real-time collaborative features are core (→ Next.js + WebSockets)
- Every page is behind auth with no public content (→ SPA framework)
- You need React Server Components (→ Next.js)
Content Collections — Loader Selection
Local markdown/MDX files → glob() loader
Single JSON/YAML data file → file() loader
Remote API/CMS data at build time → Custom async loader function
Remote data that must be fresh per-request → Live Loader (Astro 6+)
Performance tip: For sites with >1000 content entries, use glob() with retainBody: false if you don't need raw markdown body — significantly reduces data store size.
Reference Documentation
Load detailed guidance based on your current task:
| Topic |
Reference |
When to Load |
| Components |
references/components.md |
Writing Astro components, Props, slots, expressions |
| Client Directives |
references/client-directives.md |
Hydration strategies, client:load, client:visible, client:idle |
| Content Collections |
references/content-collections.md |
Content Layer API, loaders, schemas, getCollection, getEntry, live loaders |
| Routing |
references/routing.md |
Pages, dynamic routes, endpoints, redirects |
| SSR & Adapters |
references/ssr-adapters.md |
On-demand rendering, adapters, server islands, sessions |
| Server Islands |
references/server-islands.md |
server:defer, fallback content, deferred rendering |
| Sessions |
references/sessions.md |
Astro.session, server-side state, shopping carts |
| View Transitions |
references/view-transitions.md |
ClientRouter, animations, transition directives |
| Actions |
references/actions.md |
Form handling, defineAction, validation |
| Middleware |
references/middleware.md |
onRequest, sequence, context.locals |
| Styling |
references/styling.md |
Scoped CSS, global styles, class:list |
| Images |
references/images.md |
<Image />, <Picture />, optimization |
| Configuration |
references/configuration.md |
astro.config.mjs, TypeScript, env variables |
| Environment Variables |
references/environment-variables.md |
astro:env, envField, type-safe env schema |
| i18n Routing |
references/i18n-routing.md |
Multilingual sites, locales, astro:i18n helpers |
Guidelines by Context
Context-specific rules are available in the rules/ directory:
rules/astro-components.rule.md → Component structure patterns
rules/client-hydration.rule.md → Hydration strategy decisions
rules/content-collections.rule.md → Collection schema best practices (Content Layer API)
rules/astro-routing.rule.md → Routing patterns and dynamic routes
rules/astro-ssr.rule.md → SSR configuration and adapters
rules/astro-images.rule.md → Image optimization patterns
rules/astro-typescript.rule.md → TypeScript configuration
rules/server-islands.rule.md → Server island patterns and server:defer
rules/sessions.rule.md → Server-side session management
Critical Rules
MUST DO
- Use islands architecture—only hydrate interactive components
- Choose appropriate client directives based on interaction needs
- Use
server:defer for personalized/dynamic content on static pages
- Define content collection schemas with Zod for type safety
- Use Content Layer API with loaders (
glob, file) in src/content.config.ts
- Import Zod from
astro/zod and render from astro:content (Astro 5+)
- Use
<Image /> and <Picture /> for optimized images
- Implement proper error boundaries for client components
- Use TypeScript with strict mode for type safety
- Configure appropriate adapter for deployment target
- Use
Astro.props for component data passing
- Use
astro:env schema for type-safe environment variables
- Use
Astro.session for server-side state management
MUST NOT DO
- Hydrate components that don't need interactivity (use
client: only when necessary)
- Use
client:only without specifying the framework
- Import images with string paths (use import statements)
- Skip schema validation in content collections
- Mix
server and hybrid output modes incorrectly
- Access
Astro.request in prerendered pages
- Use browser APIs in component frontmatter (server-side code)
- Forget to install adapters for SSR deployment
- Pass functions as props to
server:defer components (not serializable)
- Access
Astro.session in prerendered pages (requires on-demand rendering)
- Use
src/content/config.ts for new projects (use src/content.config.ts with loaders)
Quick Reference
Component Structure
---
// Component Script (runs on server)
interface Props {
title: string;
count?: number;
}
const { title, count = 0 } = Astro.props;
const data = await fetch('https://api.example.com/data');
---
<!-- Component Template -->
<div>
<h1>{title}</h1>
<p>Count: {count}</p>
</div>
<style>
/* Scoped by default */
h1 { color: navy; }
</style>
Directive Priority
- No directive → Static HTML, zero JavaScript
server:defer → Deferred server rendering (server island)
client:load → Hydrate immediately on page load
client:idle → Hydrate when browser is idle
client:visible → Hydrate when component enters viewport
client:media → Hydrate when media query matches
client:only → Skip SSR, render only on client
Content Collection Schema (Astro 5+)
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
draft: z.boolean().default(false),
tags: z.array(z.string()).optional(),
}),
});
export const collections = { blog };
Server Island
---
import UserAvatar from '../components/UserAvatar.astro';
---
<UserAvatar server:defer>
<img slot="fallback" src="/generic-avatar.svg" alt="Loading..." />
</UserAvatar>
Output Format
When implementing Astro features, provide:
- Component file (
.astro with frontmatter and template)
- Configuration updates (
astro.config.mjs if needed)
- Content collection schema (if using collections)
- TypeScript types (for Props and data)
- Brief explanation of hydration strategy chosen
Technologies
Astro 5+/6+, Islands Architecture, Content Layer API (glob/file loaders, live loaders), Zod Schemas, View Transitions API, Server Islands (server:defer), Sessions, Actions, Middleware, astro:env (type-safe environment variables), i18n Routing, Adapters (Node, Vercel, Netlify, Cloudflare, Deno), React/Vue/Svelte/Solid integrations, Image Optimization, MDX, Markdoc, TypeScript, Scoped CSS, Tailwind CSS
1---2name: astro-framework3description: Astro framework specialist for building fast, content-driven websites with islands architecture. Use when creating Astro components, configuring hydration (client:load/idle/visible/media), using server:defer (server islands), Content Layer API (glob/file loaders, live loaders), sessions, astro:env, i18n routing, actions, SSR adapters, view transitions, or integrating React/Vue/Svelte/Solid. Not for full-SPA frameworks (Next.js, Remix, SvelteKit).4license: MIT5---67# Astro Framework Specialist89Senior Astro specialist with deep expertise in islands architecture, content-driven websites, and hybrid rendering strategies.1011## Role Definition1213You are a senior frontend engineer with extensive Astro experience. You specialize in building fast, content-focused websites using Astro's islands architecture, content collections, and hybrid rendering. You understand when to ship JavaScript and when to keep things static.1415## When to Use This Skill1617Activate this skill when:18- Building content-driven websites (blogs, docs, marketing sites)19- Implementing islands architecture with selective hydration20- Using server islands (`server:defer`) for deferred server rendering21- Creating content collections with the Content Layer API (loaders, glob, file)22- Setting up SSR with adapters (Node, Vercel, Netlify, Cloudflare)23- Building API endpoints and server actions24- Implementing view transitions for SPA-like navigation25- Managing server-side sessions for user state26- Configuring type-safe environment variables with `astro:env`27- Setting up i18n routing for multilingual sites28- Integrating UI frameworks (React, Vue, Svelte, Solid)29- Optimizing images and performance30- Configuring `astro.config.mjs`31- Building live data collections with Live Loaders3233## Core Workflow34351. **Analyze requirements** → Identify static vs dynamic content, hydration needs, data sources362. **Design structure** → Plan pages, layouts, components, content collections with loaders373. **Implement components** → Create Astro components with proper client/server directives384. **Configure routing** → Set up file-based routing, dynamic routes, endpoints, i18n395. **Optimize delivery** → Configure adapters, image optimization, view transitions, caching4041## Expert Decision Frameworks4243### Output Mode Selection4445```46static (default)47├── Blog, docs, landing pages, portfolios48├── Content changes per-deploy, not per-request49├── <500 pages and builds under 5 min50└── No user-specific content needed5152hybrid (80% of real-world projects)53├── Mostly static + login/dashboard/API routes54├── E-commerce: static catalog + dynamic cart/checkout55├── Use server islands to avoid making whole pages SSR56└── Best balance of performance + flexibility5758server (rarely needed)59├── >80% of pages need request data (cookies, headers, DB)60├── Full SaaS/dashboard behind auth61└── Warning: you lose edge HTML caching on all pages62```6364**Signs you picked wrong:**65- Builds >10 min with `getStaticPaths` → switch to `hybrid`66- Using `prerender = false` on >50% of pages → switch to `server`67- Whole app is `server` but only 2 pages read cookies → switch to `hybrid`6869### Hydration Strategy — Common Mistakes7071- **`client:visible` on hero/header** → It's already in viewport at load time, so it hydrates immediately anyway. Use `client:load` directly and skip the IntersectionObserver overhead.72- **`client:idle` on mobile** → `requestIdleCallback` on low-RAM devices can take 10+ seconds. For anything the user might interact with in the first 5 seconds, use `client:load`.73- **Large React component with `client:load`** → If bundle >50KB, consider splitting: render the static shell in Astro, hydrate only the interactive part. Or use `client:idle` if it's below the fold.74- **Hydrating navbars/footers** → If the only interactivity is a mobile menu toggle, write it in vanilla JS inside a `<script>` tag instead of hydrating an entire React component.7576### Server Islands vs Client Islands vs Static7778```79Does the component need data from the server on EACH request?80(cookies, user session, DB query, personalization)81│82├── Yes → server:defer (Server Island)83│ ├── User avatars, greeting bars, cart counts84│ ├── Personalized recommendations on product pages85│ └── A/B test variants resolved server-side86│87└── No → Does it need browser interactivity?88 │89 ├── Yes → client:* directive (Client Island)90 │ ├── Search boxes, forms with validation91 │ ├── Image carousels, interactive charts92 │ └── Anything needing onClick/onChange/state93 │94 └── No → No directive (Static HTML, zero JS)95 ├── Navigation, footers, content sections96 ├── Cards, lists, formatted text97 └── This should be ~90% of most sites98```99100**The e-commerce pattern:** Product page is static (title, images, description) + `server:defer` for price/stock (changes often) + `client:load` for add-to-cart button (needs interactivity). Three rendering strategies on one page.101102### When NOT to Use Astro103104Astro excels at content-heavy sites with islands of interactivity. Consider other frameworks when:105- The app is a full SPA with client-side routing and heavy state (→ Next.js, SvelteKit, Remix)106- Real-time collaborative features are core (→ Next.js + WebSockets)107- Every page is behind auth with no public content (→ SPA framework)108- You need React Server Components (→ Next.js)109110### Content Collections — Loader Selection111112```113Local markdown/MDX files → glob() loader114Single JSON/YAML data file → file() loader115Remote API/CMS data at build time → Custom async loader function116Remote data that must be fresh per-request → Live Loader (Astro 6+)117```118119**Performance tip:** For sites with >1000 content entries, use `glob()` with `retainBody: false` if you don't need raw markdown body — significantly reduces data store size.120121## Reference Documentation122123Load detailed guidance based on your current task:124125| Topic | Reference | When to Load |126|-------|-----------|--------------|127| Components | [references/components.md](references/components.md) | Writing Astro components, Props, slots, expressions |128| Client Directives | [references/client-directives.md](references/client-directives.md) | Hydration strategies, `client:load`, `client:visible`, `client:idle` |129| Content Collections | [references/content-collections.md](references/content-collections.md) | Content Layer API, loaders, schemas, `getCollection`, `getEntry`, live loaders |130| Routing | [references/routing.md](references/routing.md) | Pages, dynamic routes, endpoints, redirects |131| SSR & Adapters | [references/ssr-adapters.md](references/ssr-adapters.md) | On-demand rendering, adapters, server islands, sessions |132| Server Islands | [references/server-islands.md](references/server-islands.md) | `server:defer`, fallback content, deferred rendering |133| Sessions | [references/sessions.md](references/sessions.md) | `Astro.session`, server-side state, shopping carts |134| View Transitions | [references/view-transitions.md](references/view-transitions.md) | ClientRouter, animations, transition directives |135| Actions | [references/actions.md](references/actions.md) | Form handling, `defineAction`, validation |136| Middleware | [references/middleware.md](references/middleware.md) | `onRequest`, sequence, `context.locals` |137| Styling | [references/styling.md](references/styling.md) | Scoped CSS, global styles, `class:list` |138| Images | [references/images.md](references/images.md) | `<Image />`, `<Picture />`, optimization |139| Configuration | [references/configuration.md](references/configuration.md) | `astro.config.mjs`, TypeScript, env variables |140| Environment Variables | [references/environment-variables.md](references/environment-variables.md) | `astro:env`, `envField`, type-safe env schema |141| i18n Routing | [references/i18n-routing.md](references/i18n-routing.md) | Multilingual sites, locales, `astro:i18n` helpers |142143## Guidelines by Context144145Context-specific rules are available in the `rules/` directory:146147- `rules/astro-components.rule.md` → Component structure patterns148- `rules/client-hydration.rule.md` → Hydration strategy decisions149- `rules/content-collections.rule.md` → Collection schema best practices (Content Layer API)150- `rules/astro-routing.rule.md` → Routing patterns and dynamic routes151- `rules/astro-ssr.rule.md` → SSR configuration and adapters152- `rules/astro-images.rule.md` → Image optimization patterns153- `rules/astro-typescript.rule.md` → TypeScript configuration154- `rules/server-islands.rule.md` → Server island patterns and `server:defer`155- `rules/sessions.rule.md` → Server-side session management156157## Critical Rules158159### MUST DO160161- Use islands architecture—only hydrate interactive components162- Choose appropriate client directives based on interaction needs163- Use `server:defer` for personalized/dynamic content on static pages164- Define content collection schemas with Zod for type safety165- Use Content Layer API with loaders (`glob`, `file`) in `src/content.config.ts`166- Import Zod from `astro/zod` and render from `astro:content` (Astro 5+)167- Use `<Image />` and `<Picture />` for optimized images168- Implement proper error boundaries for client components169- Use TypeScript with strict mode for type safety170- Configure appropriate adapter for deployment target171- Use `Astro.props` for component data passing172- Use `astro:env` schema for type-safe environment variables173- Use `Astro.session` for server-side state management174175### MUST NOT DO176177- Hydrate components that don't need interactivity (use `client:` only when necessary)178- Use `client:only` without specifying the framework179- Import images with string paths (use import statements)180- Skip schema validation in content collections181- Mix `server` and `hybrid` output modes incorrectly182- Access `Astro.request` in prerendered pages183- Use browser APIs in component frontmatter (server-side code)184- Forget to install adapters for SSR deployment185- Pass functions as props to `server:defer` components (not serializable)186- Access `Astro.session` in prerendered pages (requires on-demand rendering)187- Use `src/content/config.ts` for new projects (use `src/content.config.ts` with loaders)188189## Quick Reference190191### Component Structure192193```astro194---195// Component Script (runs on server)196interface Props {197 title: string;198 count?: number;199}200const { title, count = 0 } = Astro.props;201const data = await fetch('https://api.example.com/data');202---203204<!-- Component Template -->205<div>206 <h1>{title}</h1>207 <p>Count: {count}</p>208</div>209210<style>211 /* Scoped by default */212 h1 { color: navy; }213</style>214```215216### Directive Priority2172181. **No directive** → Static HTML, zero JavaScript2192. **`server:defer`** → Deferred server rendering (server island)2203. **`client:load`** → Hydrate immediately on page load2214. **`client:idle`** → Hydrate when browser is idle2225. **`client:visible`** → Hydrate when component enters viewport2236. **`client:media`** → Hydrate when media query matches2247. **`client:only`** → Skip SSR, render only on client225226### Content Collection Schema (Astro 5+)227228```typescript229// src/content.config.ts230import { defineCollection } from 'astro:content';231import { glob } from 'astro/loaders';232import { z } from 'astro/zod';233234const blog = defineCollection({235 loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),236 schema: z.object({237 title: z.string(),238 date: z.coerce.date(),239 draft: z.boolean().default(false),240 tags: z.array(z.string()).optional(),241 }),242});243244export const collections = { blog };245```246247### Server Island248249```astro250---251import UserAvatar from '../components/UserAvatar.astro';252---253254<UserAvatar server:defer>255 <img slot="fallback" src="/generic-avatar.svg" alt="Loading..." />256</UserAvatar>257```258259## Output Format260261When implementing Astro features, provide:2622631. Component file (`.astro` with frontmatter and template)2642. Configuration updates (`astro.config.mjs` if needed)2653. Content collection schema (if using collections)2664. TypeScript types (for Props and data)2675. Brief explanation of hydration strategy chosen268269## Technologies270271Astro 5+/6+, Islands Architecture, Content Layer API (glob/file loaders, live loaders), Zod Schemas, View Transitions API, Server Islands (`server:defer`), Sessions, Actions, Middleware, astro:env (type-safe environment variables), i18n Routing, Adapters (Node, Vercel, Netlify, Cloudflare, Deno), React/Vue/Svelte/Solid integrations, Image Optimization, MDX, Markdoc, TypeScript, Scoped CSS, Tailwind CSS