name: astro-builder description: Comprehensive skill for building websites with Astro.build. Use when the user wants to create a website using Astro, needs to select an appropriate theme from Astro's free themes collection, requires access to Astro documentation, or wants to develop Astro components and pages. This skill handles theme selection, documentation access, project setup, and Astro-specific development patterns including islands architecture, content collections, and view transitions.
Astro Website Builder
This skill helps you build websites with Astro.build by guiding you through theme selection, documentation access, and development best practices. Use this skill whenever a user mentions building with Astro, wants to create a website, or needs help with Astro-specific features.
When to Use This Skill
Activate this skill when:
- User mentions "Astro" or "astro.build" in their request
- User wants to build a website and Astro would be appropriate (blogs, documentation, portfolios, marketing sites, content-driven sites)
- User needs to select a theme for their Astro project
- User needs help with Astro components, routing, islands architecture, or configuration
- User wants to integrate React, Vue, Svelte, Solid, or other frameworks with Astro
- User needs access to Astro's documentation or best practices
- User wants to implement content collections, view transitions, or server islands
Core Astro Concepts
Islands Architecture
Astro pioneered the islands architecture pattern:
- Pages render as static HTML by default (zero JavaScript)
- Interactive components become "islands" of interactivity
- Use
client:*directives to hydrate specific components - Available directives:
client:load,client:idle,client:visible,client:media - Multiple framework islands can coexist on the same page
Server-First Approach
- Astro is a Multi-Page App (MPA) framework, not an SPA
- Rendering happens on the server (build-time or on-demand)
- Results in 40% faster load times with 90% less JavaScript vs typical SPAs
- Client-side interactivity is opt-in, not mandatory
Server Islands (New Feature)
- Use
server:deferdirective on Astro components for deferred server rendering - Allows personalized/dynamic content without blocking page load
- Combines static HTML with dynamic server-generated components
- Perfect for user avatars, personalized content, or slow API calls
Workflow Overview
When building an Astro website, follow this process:
- Understand Requirements - Determine the type of website and features needed
- Select Appropriate Theme - Choose from Astro's free themes based on requirements
- Access Documentation - Reference Astro docs for specific features
- Initialize Project - Set up the project structure
- Develop Components - Build using Astro's component architecture
- Add Interactivity - Implement islands for client-side functionality
- Optimize & Deploy - Follow best practices for performance
Step 1: Understand Requirements
First, identify the type of website and its requirements:
Website Types Best Suited for Astro:
- Blog/Publication site (excellent fit)
- Portfolio/Showcase (excellent fit)
- Documentation site (use Starlight)
- Marketing/Landing page (excellent fit)
- E-commerce site (good fit)
- Company/Business site (excellent fit)
- Personal website (excellent fit)
- Community sites
- Any content-driven website
Key Questions to Ask:
- What is the primary purpose of the site?
- What content types will it have? (blog posts, projects, products, etc.)
- Does it need interactivity? (forms, search, dynamic content)
- What frameworks does the user prefer? (React, Vue, Svelte, Solid, Preact, etc.)
- Does it need specific features? (dark mode, i18n, CMS integration, view transitions)
- Will content be managed via content collections or a headless CMS?
- Does it need on-demand rendering or is static generation sufficient?
Step 2: Select Appropriate Theme
Use web_fetch to browse free themes with appropriate filters:
Base URL for themes:
https://astro.build/themes/1/
Available filters:
- Technology:
?technology[]=react,technology[]=vue,technology[]=svelte,technology[]=tailwind - Price:
?price[]=free,price[]=premium - Features: Content collections, dark mode, i18n, etc.
Example fetches:
# Free React-compatible themes
https://astro.build/themes/1/?search=&technology%5B%5D=react&price%5B%5D=free
# Free Tailwind themes
https://astro.build/themes/1/?search=&technology%5B%5D=tailwind&price%5B%5D=free
# All free themes
https://astro.build/themes/1/?price%5B%5D=free
Theme Selection Criteria:
For Blogs/Publications:
- Look for content collections support
- Strong typography and reading experience
- Must support Markdown/MDX
- Should have tags/categories
- RSS feed support
- Consider: astro-paper, astro-blog-template
For Portfolios:
- Visual project showcase capabilities
- About/Contact sections
- Smooth animations and transitions
- Image optimization
- Consider themes with view transitions
For Documentation:
- Strongly recommend Starlight (official Astro docs framework)
- Features: Built-in search, sidebar navigation, dark mode, i18n
- Best for: Technical docs, API references, guides
- Installation:
npm create astro@latest -- --template starlight
For Landing Pages:
- Hero section with CTA
- Features/Benefits sections
- Contact forms
- Conversion-optimized design
- Fast loading for better SEO
For E-commerce:
- Product listings and filters
- Shopping cart functionality
- Payment integration ready
- Product detail pages
- Content collections for products
Action: Fetch the themes page, analyze available themes, and recommend 2-3 options that best match the user's requirements. Explain why each theme is suitable and highlight key features.
Step 3: Access Astro Documentation
Documentation Hierarchy:
Built-in Reference (First Priority):
references/astro_docs.md- Contains core Astro concepts, syntax, and common patterns
- READ THIS FIRST for most questions
Full LLM-Optimized Docs:
https://docs.astro.build/llms-full.txt- Comprehensive, LLM-friendly format
- Use for advanced features and detailed reference
Web Documentation:
https://docs.astro.build- Official docs site
- Use for latest updates or visual guides
When to Reference Documentation:
- Component syntax questions → Reference astro_docs.md
- Routing and pages → Reference astro_docs.md
- Styling options → Reference astro_docs.md
- Islands architecture → Fetch LLM docs or reference built-in docs
- Content collections → Fetch LLM docs
- View transitions → Fetch LLM docs
- Server islands → Fetch LLM docs
- Integration setup → Fetch LLM docs
- Advanced configuration → Fetch LLM docs
- API details → Fetch LLM docs
Step 4: Initialize Astro Project
Using Create Astro CLI (Recommended)
Standard new project:
npm create astro@latest
With specific template:
npm create astro@latest -- --template <theme-github-username>/<theme-repo>
With Starlight (for documentation):
npm create astro@latest -- --template starlight
With integrations pre-installed:
npm create astro@latest -- --add react --add partytown
Supported integrations for --add flag:
- Framework integrations:
react,preact,vue,svelte,solid - Other integrations:
tailwind,partytown,mdx,sitemap
Prerequisites
Node.js version requirements:
v18.20.8or higherv20.3.0or higherv22.0.0or higher- Note:
v19andv21are NOT supported
Recommended tools:
- VS Code with Official Astro extension
- Terminal for CLI access
Project Structure Setup
After initialization, ensure proper structure:
project/
├── src/
│ ├── components/ # Reusable components
│ ├── layouts/ # Page layouts
│ ├── pages/ # Routes (REQUIRED - file-based routing)
│ │ ├── index.astro # Homepage (/)
│ │ ├── about.astro # About page (/about)
│ │ ├── blog/
│ │ │ └── [...slug].astro # Dynamic blog routes
│ │ ├── 404.astro # Custom 404 page
│ │ └── 500.astro # Custom 500 page (on-demand rendering only)
│ ├── content/ # Content collections (recommended for blogs)
│ │ └── config.ts # Content collections config
│ ├── assets/ # Optimized images and assets
│ └── styles/ # Global styles (optional)
├── public/ # Static assets (copied as-is)
│ ├── favicon.svg
│ └── robots.txt
├── astro.config.mjs # Astro configuration
├── package.json # Dependencies and scripts
└── tsconfig.json # TypeScript config
Critical Notes:
- The
src/pages/directory is REQUIRED for routing to work - Only
src/pages/is a reserved directory - others are conventional but optional - Files in
public/are served as-is (not processed or optimized) - Files in
src/are processed, optimized, and bundled
Step 5: Develop Components and Pages
Astro Component Structure
Every Astro component has two parts:
- Component Script (Frontmatter) - between
---fences - Component Template - HTML with Astro syntax
Basic component example:
---
// Component Script - runs at build time (server-side)
// Import other components
import Button from './Button.astro';
// Define props with TypeScript
interface Props {
title: string;
description?: string;
}
const { title, description = "Default description" } = Astro.props;
// Fetch data (this is safe - runs server-side only)
const data = await fetch('API_URL').then(r => r.json());
---
<!-- Component Template - HTML output -->
<article>
<h2>{title}</h2>
{description && <p>{description}</p>}
<Button />
</article>
<style>
/* Scoped styles - only apply to this component */
article {
padding: 1rem;
border: 1px solid #ccc;
}
</style>
Component Development Best Practices
- Props with TypeScript:
---
interface Props {
title: string;
count?: number;
items: string[];
}
const { title, count = 0, items } = Astro.props;
---
- Default values:
---
const {
greeting = "Hello",
name = "Astronaut"
} = Astro.props;
---
- Component imports:
---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
import { Icon } from 'astro-icon';
---
Slots for Component Composition
Default slot:
<!-- Wrapper.astro -->
<div class="wrapper">
<slot /> <!-- children go here -->
</div>
Named slots:
<!-- Layout.astro -->
<div>
<header>
<slot name="header" /> <!-- for header content -->
</header>
<main>
<slot /> <!-- default slot -->
</main>
<footer>
<slot name="footer" /> <!-- for footer content -->
</footer>
</div>
Using named slots:
<Layout>
<h1 slot="header">My Site</h1>
<p>Main content here</p>
<p slot="footer">© 2026</p>
</Layout>
Slot fallback content:
<slot>
<p>This shows if no content is provided</p>
</slot>
Page Development Pattern
Simple page:
---
import Layout from '../layouts/Layout.astro';
const title = "My Page";
---
<Layout title={title}>
<h1>{title}</h1>
<p>Content here</p>
</Layout>
Page with data fetching:
---
import Layout from '../layouts/Layout.astro';
const response = await fetch('https://api.example.com/data');
const data = await response.json();
---
<Layout title="Data Page">
<ul>
{data.map(item => (
<li>{item.name}</li>
))}
</ul>
</Layout>
Dynamic route with getStaticPaths:
---
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
const posts = await fetchBlogPosts();
return posts.map(post => ({
params: { slug: post.slug },
props: { post }
}));
}
const { post } = Astro.props;
---
<h1>{post.title}</h1>
<p>{post.content}</p>
Step 6: Adding Interactivity with Islands
The Islands Pattern
By default, ALL components render to static HTML with zero JavaScript. To add interactivity:
- Install framework integration:
npx astro add react
# or
npx astro add vue
# or
npx astro add svelte
# or
npx astro add solid
# or
npx astro add preact
- Create framework component:
// src/components/Counter.jsx
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
- Use with client directive:
---
import Counter from '../components/Counter.jsx';
---
<!-- Static - no JavaScript sent -->
<Counter />
<!-- Interactive - hydrates immediately -->
<Counter client:load />
<!-- Interactive - hydrates when idle -->
<Counter client:idle />
<!-- Interactive - hydrates when visible -->
<Counter client:visible />
<!-- Interactive - hydrates based on media query -->
<Counter client:media="(max-width: 768px)" />
<!-- Only JavaScript, no server rendering -->
<Counter client:only="react" />
Client Directives Explained
client:load- Hydrate immediately on page load (high priority)client:idle- Hydrate when browser is idle (recommended for most)client:visible- Hydrate when component enters viewport (best for below-fold)client:media="(query)"- Hydrate when media query matchesclient:only="framework"- Skip server rendering, client-side only
Performance tip: Use client:idle or client:visible by default. Only use client:load for critical interactive elements.
Server Islands (New Feature)
For dynamic server-rendered content that can load after the main page:
---
import UserAvatar from '../components/UserAvatar.astro';
import RecentPosts from '../components/RecentPosts.astro';
---
<header>
<!-- Deferred server rendering - won't block page load -->
<UserAvatar server:defer>
<!-- Fallback content shown while loading -->
<div slot="fallback" class="skeleton-avatar"></div>
</UserAvatar>
</header>
<main>
<h1>Welcome!</h1>
<!-- Immediate content loads first -->
</main>
<aside>
<!-- Another server island with fallback -->
<RecentPosts server:defer>
<div slot="fallback">Loading posts...</div>
</RecentPosts>
</aside>
Step 7: Content Collections (Recommended for Blogs)
Content collections provide type-safe content management:
1. Define schema in src/content/config.ts:
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
description: z.string(),
publishDate: z.date(),
tags: z.array(z.string()),
image: z.string().optional(),
}),
});
export const collections = { blog };
2. Create content in src/content/blog/:
---
title: "My First Post"
description: "This is my first blog post"
publishDate: 2026-02-06
tags: ["astro", "blogging"]
---
Content here in Markdown!
3. Query in pages:
---
import { getCollection } from 'astro:content';
const blogPosts = await getCollection('blog');
const sortedPosts = blogPosts.sort((a, b) =>
b.data.publishDate.valueOf() - a.data.publishDate.valueOf()
);
---
{sortedPosts.map(post => (
<article>
<h2><a href={`/blog/${post.slug}`}>{post.data.title}</a></h2>
<p>{post.data.description}</p>
</article>
))}
4. Render individual posts:
---
// src/pages/blog/[...slug].astro
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<article>
<h1>{post.data.title}</h1>
<time>{post.data.publishDate.toLocaleDateString()}</time>
<Content />
</article>
Step 8: View Transitions
Add smooth page transitions with minimal code:
1. Add to layout:
---
import { ViewTransitions } from 'astro:transitions';
---
<html>
<head>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>
2. Customize transitions on elements:
<img src="photo.jpg" transition:name="hero" />
<h1 transition:animate="slide">Title</h1>
3. Control transition behavior:
---
// Disable transitions for this page
export const transitionDisable = true;
---
Configuration & Optimization
Essential Astro Config Options
// astro.config.mjs
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
import tailwind from "@astrojs/tailwind";
export default defineConfig({
// Site URL for sitemaps and canonical URLs
site: "https://example.com",
// Base path if deploying to subdirectory
base: "/docs",
// Trailing slash preference
trailingSlash: "always", // or 'never' or 'ignore'
// Output mode
output: "static", // or 'server' or 'hybrid'
// Integrations
integrations: [react(), tailwind()],
// Image optimization
image: {
domains: ["example.com"],
},
// Markdown options
markdown: {
shikiConfig: {
theme: "dracula",
},
},
});
Performance Best Practices
Keep islands minimal:
- Only use
client:*directives when truly needed - Prefer static HTML whenever possible
- Use
client:idleorclient:visibleoverclient:load
- Only use
Optimize images:
---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<Image src={heroImage} alt="Hero" width={800} height={600} />
Use content collections for type safety:
- Define schemas for all content
- Get autocomplete and type checking
- Validate content at build time
Implement proper caching headers:
- Configure in your hosting platform
- Use aggressive caching for static assets
Minimize client-side JavaScript:
- Astro's default is zero JS - keep it that way
- Only add interactivity where needed
- Consider using
<script>tags for simple interactions
Troubleshooting
Common Issues & Solutions
"Module not found" errors:
- Check import paths are correct
- Verify integrations are installed:
npm install - Check
astro.config.mjshas correct integration setup - Try clearing node_modules and reinstalling
"Page not rendering":
- Verify file is in
src/pages/directory - Check for syntax errors in frontmatter (between
---) - Ensure proper file extension (
.astro,.md,.mdx) - Check for TypeScript errors if using TS
"Styles not applying":
- Remember: scoped styles only apply to component's own HTML
- Use
<style is:global>for global styles - Check Tailwind configuration if using Tailwind
- Verify CSS is being imported correctly
"Component not interactive":
- Add
client:*directive to framework components - Ensure integration is installed (e.g.,
@astrojs/react) - Check browser console for JavaScript errors
- Verify the component actually needs client-side JS
"Content collection errors":
- Check schema in
src/content/config.ts - Verify frontmatter matches schema
- Ensure
type: 'content'is set correctly - Check file is in correct collection folder
"Node.js version errors":
- Verify you're using Node.js v18.20.8+, v20.3.0+, or v22+
- Avoid v19 and v21 (not supported)
- Use nvm to manage Node versions
Key Differences from Original Skill
Major Updates:
- Server Islands: New
server:deferdirective for personalized content - Node.js Requirements: Updated version requirements (v19, v21 not supported)
- Content Collections: Emphasized as best practice for content management
- View Transitions: Built-in support for smooth page transitions
- Installation Flags: New
--addflag for installing integrations during setup - 500 Error Pages: New support for custom 500 pages with error props
- Islands Architecture: More detailed explanation of the core concept
- Performance Focus: Stronger emphasis on zero-JS defaults
- TypeScript: Better TypeScript integration and examples
- Starlight: Highlighted as official solution for documentation sites
Example Workflows
Example 1: Building a Blog with Content Collections
User: "I want to build a blog with Astro and React"
Workflow:
- Identify requirements: Blog site, needs React support, wants type-safe content
- Fetch themes:
web_fetch https://astro.build/themes/1/?technology[]=react&price[]=free - Recommend theme: Suggest astro-blog-template or similar
- Initialize project:
npm create astro@latest my-blog -- --template <theme-name> --add react - Set up content collections for blog posts
- Create blog post schema with title, date, description, tags
- Build listing page that queries all posts
- Create dynamic route for individual posts
- Add React components for interactive elements (likes, comments) with
client:visible - Implement view transitions for smooth navigation
- Configure site URL and metadata
Example 2: Documentation Site with Starlight
User: "I need documentation site with search and dark mode"
Workflow:
- Identify: Documentation site, needs search and dark mode
- Strongly recommend Starlight (official Astro docs framework)
- Initialize:
npm create astro@latest my-docs -- --template starlight - Configure sidebar in
astro.config.mjs:starlight({ title: "My Docs", sidebar: [ { label: "Guides", autogenerate: { directory: "guides" } }, { label: "Reference", autogenerate: { directory: "reference" } }, ], }); - Create content in
src/content/docs/ - Dark mode works automatically
- Search works automatically (powered by Pagefind)
- Customize theme colors if needed
Example 3: E-commerce Site with Product Collections
User: "Build an e-commerce store for selling art prints"
Workflow:
- Identify requirements: Product showcase, shopping cart, payment integration
- Fetch themes for e-commerce or portfolio
- Initialize project with React (for cart interactivity)
- Set up content collection for products:
const products = defineCollection({ type: "content", schema: z.object({ name: z.string(), price: z.number(), image: z.string(), category: z.enum(["abstract", "landscape", "portrait"]), inStock: z.boolean(), }), }); - Create product listing page with filters
- Build product detail pages with dynamic routes
- Add React shopping cart component with
client:load - Integrate payment processor (Stripe, etc.)
- Optimize product images with Astro's Image component
- Implement view transitions for smooth browsing
Resources Reference
Documentation Sources
- Primary:
references/astro_docs.md(read first) - Comprehensive:
https://docs.astro.build/llms-full.txt - Official:
https://docs.astro.build
Theme Resources
- Themes Gallery:
https://astro.build/themes/ - Free Themes:
https://astro.build/themes/1/?price[]=free
Community
- Discord:
https://astro.build/chat - GitHub:
https://github.com/withastro/astro
Success Criteria
An Astro project is set up correctly when:
✅ Project structure follows Astro conventions
✅ src/pages/ directory exists with at least index.astro
✅ Appropriate theme selected based on requirements
✅ Components follow Astro syntax patterns
✅ TypeScript interfaces defined for component props
✅ Client-side interactivity only added where needed with proper directives
✅ Images optimized using <Image> component from astro:assets
✅ Content collections configured if blog/content-heavy site
✅ Site runs successfully with npm run dev
✅ Build completes without errors: npm run build
✅ Configuration includes site URL and proper integrations
Key Reminders
- Always read
references/astro_docs.mdFIRST before answering questions - Fetch themes from the Astro themes page when user needs a starting point
- Use web_fetch for full docs when needed for advanced topics
- Islands are opt-in - components are static by default (zero JS)
- Content collections - Best practice for blogs and content-driven sites
- Server islands - New feature for personalized content without blocking
- View transitions - Easy to add smooth navigation
- Starlight - Official solution for documentation (use instead of generic themes)
- Type safety - Use TypeScript for props and content schemas
- Performance - It should be nearly impossible to build a slow Astro site