---
name: astro-static-site
description: "Ship zero-JS static sites with Astro: islands architecture, MDX blog, and Vercel edge. Generates Astro 4 pages with the islands architecture pattern — server-rendered shells with selective React/Vue/Svelte hydration. Configures MDX for content collections, image optimisation, and sitemap generation."
license: MIT
---

# Astro Static Site Builder

Scaffolds production-ready Astro 4 sites that ship zero JavaScript by default and hydrate interactive components only where you actually need them. It's built for developers putting up marketing sites, documentation, or content-heavy blogs who want fast static output but don't want to give up React, Vue, or Svelte components when a page genuinely needs interactivity.

## When to use it

- You're building a blog or docs site and want Markdown/MDX backed by typed content collections.
- You have a mostly-static page with one or two interactive widgets (a search box, a carousel, a like button) and don't want to ship a full SPA bundle.
- You're migrating a Next.js or Gatsby site that was over-shipping client JS.
- You need clean SEO output: pre-rendered HTML, a generated sitemap, and Open Graph tags.

## What it does

The skill generates a project around Astro's core primitives:

- **Islands architecture** via client directives — `client:load`, `client:idle`, `client:visible`, and `client:only` — so each framework component decides its own hydration strategy.
- **Content collections** defined in `src/content/config.ts` with Zod schemas, queried through `getCollection()` and `getEntry()`. MDX is wired up via `@astrojs/mdx` so you can import components inside `.mdx` files.
- **Image optimisation** using Astro's `<Image />` and `<Picture />` components from `astro:assets`, which emit responsive `srcset` and modern formats at build time.
- **Sitemap + SEO** through `@astrojs/sitemap` and per-page `<head>` metadata.
- **Framework adapters** — `@astrojs/react`, `@astrojs/vue`, or `@astrojs/svelte` — registered in `astro.config.mjs`. For dynamic routes it sets up the Vercel adapter (`@astrojs/vercel`) when you opt into SSR/edge.

## Usage

```bash
curl -fsSL --create-dirs -o ~/.claude/skills/astro-static-site/SKILL.md https://claudeskil.com/skills/astro-static-site/SKILL.md

# then, in your repo:
claude "scaffold an Astro blog with MDX, a React search island, and Vercel deploy"
```

A generated config looks like:

```js
// astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import react from '@astrojs/react';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  integrations: [mdx(), react(), sitemap()],
});
```

```astro
---
import Search from '../components/Search.jsx';
---
<Search client:visible />
```

## Tips & gotchas

- A component without a `client:*` directive renders to static HTML and ships **no** JS — that's the point, not a bug. Add the directive only when you need interactivity.
- `client:only="react"` skips server rendering entirely; you must name the framework or hydration silently fails.
- Props passed across the island boundary are serialized to JSON. Functions and class instances won't survive — pass plain data.
- Set `site` in `astro.config.mjs` or `@astrojs/sitemap` produces no output and canonical URLs break.

## FAQ

**Can I mix React and Vue on the same page?** Yes. Astro renders multiple frameworks side by side; each island hydrates independently with its own runtime.

**Does it support SSR, or only static?** Both. It defaults to static (`output: 'static'`) and switches to `'server'` with the Vercel adapter when you need on-demand or edge rendering.

**How are drafts handled?** Add a boolean field to your collection schema and filter on it in `getCollection()`.
