Skill: Astro Patterns
Purpose
Guide Claude Code when building Astro sites (landing pages, marketing, docs). Targets Astro 5.x. Follow these conventions unless the project's CLAUDE.md overrides them.
Project Structure
- File-based routing from
src/pages/ - Components in
src/components/organized by section (layout/,landing/,ui/) - Layout templates in
src/layouts/ - Content collections in
src/content/with schema insrc/content.config.ts - Global styles in
src/styles/ - Static assets in
public/ @/*path alias via tsconfig
Components (.astro files)
- Code fence (
---) for server-only TypeScript — never sent to browser - Define
Propsinterface above usage, destructure fromAstro.props - PascalCase filenames matching component name (
Hero.astro,FeatureGrid.astro) - Scoped
<style>by default — useis:globalonly when intentional - Prefer
.astrocomponents over framework components unless interactivity is needed - Use
<slot />for child content; named slots with<slot name="footer" />
Islands (Interactive Components)
- Only add
client:*directives when JavaScript interactivity is truly required client:load— immediately interactive (nav menus, forms with validation)client:idle— hydrate when browser idle (carousels, counters)client:visible— hydrate when scrolled into view (comment sections, chat)server:defer— defer server rendering for personalized content- Each island hydrates independently — keep them small and self-contained
- To add a framework:
npx astro add react(or vue, svelte, solid) inside the container - No framework integration is installed by default — add only when you need an island
Pages & Routing
- Each
.astrofile insrc/pages/= one route (index.astro→/,about.astro→/about) - Wrap page content in a layout component:
<BaseLayout title="About">...</BaseLayout> - Dynamic routes use
[param].astroor[...slug].astrowithgetStaticPaths() - Set page metadata via layout props (
title,description) - Always create
src/pages/404.astrofor custom 404
Content Collections
- Define schemas in
src/content.config.tsusingdefineCollectionwith Zod - Query with
getCollection('blog')/getEntry('blog', 'my-post') - Render markdown content with the
<Content />component - Frontmatter is type-safe and validated at build time
Styling
- Tailwind v4 via
@tailwindcss/viteplugin (Astro uses Vite natively) - DaisyUI as
@plugin "daisyui"in global CSS - DaisyUI semantic colors:
base-100,base-content,primary— never hardcoded hex - Scoped
<style>in.astrofiles for component-specific overrides - Responsive-first: mobile breakpoints before desktop
Naming
- Components: PascalCase (
Hero.astro,FeatureCard.astro) - Pages: kebab-case matching URL slugs (
about-us.astro,contact.astro) - Layouts: PascalCase with Layout suffix (
BaseLayout.astro,BlogLayout.astro) - Content collections: kebab-case directories and files
- CSS custom properties:
--color-*,--font-*,--spacing-*
Development Environment
- All commands run via
make(Docker Compose under the hood) — never runnpmdirectly on host - Use
/astro-bootstrapwhen setting up a new project from scratch make devstarts the dev server (default port 4321)make astro-checkfor TypeScript and template validationmake buildfor production static build,make previewto test it locally
SEO & Performance
- Set
<title>and<meta name="description">on every page via layout props - Use
<ViewTransitions />fromastro:transitionsfor smooth page navigation - Images: use
<Image>fromastro:assetsfor automatic optimization - Fonts: self-host via
@fontsourcepackages — no external CDN requests - Include OG tags (
og:title,og:description,og:image) on all pages - Add
@astrojs/sitemapintegration for automatic sitemap generation - Place
robots.txtand favicons inpublic/