<!-- skill: Astro Sites | version: 1.0.0 | description: Astro islands, content collections and fast SSG/SSR deploys | category: Web -->
## Instructions
- Islands first: `.astro` static by default, hydrate only with `client:load|idle|visible|media` on framework components (React/Vue/Svelte); default to zero JS, audit with `astro check` + Lighthouse.
- Routing: `src/pages/index.astro` + `[...slug].astro` dynamic, `src/layouts/Base.astro` with `<slot/>`, `src/middleware.ts` for auth/headers, `getStaticPaths()` for SSG params.
- Content collections: `src/content/config.ts` with `zod` schemas (`blog`, `docs`), `getCollection('blog')` + `getEntry()`, Markdown/MDX with frontmatter validated at build.
- View Transitions: `<ViewTransitions />` in head + `transition:animate="slide"` directives for SPA-like nav; scope per-element, test reduced-motion fallback.
- SSR vs SSG: `output: 'static'` default; `output: 'server'` + adapter (`@astrojs/node|vercel|cloudflare`) for dynamic; per-page `export const prerender = true/false` hybrid.
- Data fetching: top-level `await fetch()` in `.astro` frontmatter (server-only, secrets safe); client islands fetch from `/api/*.ts` endpoints via `APIRoute`.
- Styling: scoped `<style>` in `.astro`, global `src/styles/global.css`, Tailwind `@astrojs/tailwind` integration; `astro:assets` `<Image>` with AVIF + `widths` + `sizes`.
- MDX power: `@astrojs/mdx` for interactive docs (charts, demos as islands), `remark-toc` + `rehype-autolink` for TOC/anchors, Shiki highlight with dark/light themes.
- API routes: `src/pages/api/contact.ts` exporting `POST: APIRoute`, validate + rate-limit, return `new Response(JSON.stringify(...), {status})`; never expose keys to islands.
- SEO: `astro-seo` or manual `<title>/<meta>/<link rel=canonical>` in layout, `src/pages/sitemap.xml.ts` or `@astrojs/sitemap`, `robots.txt` in `public/`, OG images via `astro-og-canvas`.
- Env: `import.meta.env.PUBLIC_*` client-safe, `process.env`/private only in frontmatter/server routes; validate with `astro:env` schema (`envField.string`).
- Deploy: `astro build` → `dist/`; Node `HOST=0.0.0.0 node ./dist/server/entry.mjs`, Vercel/Netlify/Cloudflare adapters zero-config, set `site:` in config for canonical URLs.
## Examples
- Docs site: content collection `docs` + Starlight theme, MDX demos as `client:visible` islands, View Transitions between pages, sitemap + search index build step.
- Marketing + blog: SSG prerendered posts with `getStaticPaths`, `<Image>` hero AVIF, `/api/newsletter.ts` signup endpoint, deploy static to Cloudflare Pages.
- Hybrid SaaS: `output:'server'` with prerendered `/` + `/pricing`, SSR `/app/*` behind middleware auth, `/api/billing-webhook.ts` Stripe handler.
## Workflows
1. Scaffold: `npm create astro@latest` (blog/empty), add `@astrojs/tailwind @astrojs/mdx @astrojs/sitemap`, set `site:` URL.
2. Model content: `src/content/config.ts` schemas, seed `blog/*.md`, build `[...slug].astro` with `getStaticPaths` + `getCollection`.
3. Add islands: framework component with `client:visible`, keep props serializable, measure JS with `astro build` output.
4. Add dynamic: `output:'server'` + adapter if needed, `middleware.ts`, `api/*.ts` endpoints, `prerender` flags per route.
5. Ship: `astro check` + `astro build` + `astro preview`, Lighthouse 95+, sitemap/OG verified, deploy static or adapter target.
## Templates
- Content collection + dynamic route:
```ts
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
export const collections = {
  blog: defineCollection({ type: 'content',
    schema: z.object({ title: z.string(), date: z.date(), excerpt: z.string(), draft: z.boolean().default(false) }) })
};
// src/pages/blog/[...slug].astro
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
  const posts = await getCollection('blog', ({ data }) => !data.draft);
  return posts.map((p) => ({ params: { slug: p.slug }, props: { post: p } }));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<Base title={post.data.title}><Content /></Base>
```
- Layout with View Transitions + SEO:
```astro
---
// src/layouts/Base.astro
import { ViewTransitions } from 'astro:transitions';
const { title, desc } = Astro.props;
---
<html lang="en"><head><meta charset="utf-8" />
<title>{title}</title><meta name="description" content={desc} />
<link rel="canonical" href={Astro.url.href} />
<ViewTransitions /></head>
<body><slot /></body></html>
```
- API endpoint + island usage:
```ts
// src/pages/api/contact.ts
import type { APIRoute } from 'astro';
export const POST: APIRoute = async ({ request }) => {
  const { email, msg } = await request.json();
  if (!email?.includes('@')) return new Response(JSON.stringify({ error: 'bad email' }), { status: 400 });
  await saveLead({ email, msg }); // DB/mail call
  return new Response(JSON.stringify({ ok: true }), { status: 200 });
};
```
```tsx
// src/components/Signup.tsx (client:visible island)
import { useState } from 'react';
export default function Signup() {
  const [email, setEmail] = useState('');
  return <form onSubmit={async (e) => { e.preventDefault();
    await fetch('/api/contact', { method: 'POST', body: JSON.stringify({ email, msg: 'hi' }) }); }}>
    <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="you@x.com" />
    <button>Join</button></form>;
}
```
## Tools
- SARAH shell_run for `astro dev/build/preview/check`, Lighthouse, `wrangler deploy` / `vercel deploy`.
- SARAH file_write for pages/layouts/content-config/api-routes; web_fetch for Astro docs + adapter guides.
## Advanced
- Hybrid tuning: `export const prerender = true` on marketing, `routeRules`-like middleware caching, `Astro.response.headers.set('Cache-Control','s-maxage=300')` for CDN on SSR pages.
- Image pipeline: `<Image src={hero} widths={[400,800,1200]} sizes="(max-width:800px) 100vw, 800px" formats={['avif','webp']} />`, `getImage()` for OG generation, ` densities` for retina icons.
- Starlight/docs ops: `sidebar` autogenerate, `editLink`, Algolia/Pagefind search hook, `astro build` link-check, Cloudflare Pages `_headers` caching for `/_astro/*` immutable assets.
## Documentation
- https://docs.astro.build/en/getting-started/
- https://docs.astro.build/en/guides/content-collections/
- https://docs.astro.build/en/guides/view-transitions/
- https://docs.astro.build/en/guides/server-side-rendering/
- https://docs.astro.build/en/guides/deploy/
