astro-framework

Build Astro websites using components, pages, layouts, content collections, routing, SSR, View Transitions, and integrations. Use when creating Astro projects, .astro files, content collections, server islands, actions, or when asking about Astro patterns, Islands Architecture, or static site generation.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "astro-framework" with this command: npx skills add migueldialpad/skills/migueldialpad-skills-astro-framework

Astro Framework

Astro is a web framework for building content-driven websites. Ships zero JavaScript by default using Islands Architecture.

Quick Start

# Create new project (choose your package manager)
npm create astro@latest
pnpm create astro@latest
bun create astro@latest

# Add integrations
npx astro add react tailwind
bunx astro add react tailwind

Package Manager Commands

Tasknpmbun
Create projectnpm create astro@latestbun create astro@latest
Dev servernpm run devbun dev
Buildnpm run buildbun run build
Previewnpm run previewbun preview
Add integrationnpx astro add <name>bunx astro add <name>
Check typesnpx astro checkbunx astro check

Project Structure

src/
├── pages/          # File-based routing (REQUIRED)
├── components/     # Reusable .astro components
├── layouts/        # Page templates with <slot/>
├── content/        # Content collections
├── styles/         # CSS/SCSS files
├── assets/         # Optimized images
public/             # Static assets (unprocessed)
astro.config.mjs    # Configuration
content.config.ts   # Collection schemas

Component Anatomy

---
// Component Script (runs on server, never sent to client)
import Header from './Header.astro';
import { getCollection } from 'astro:content';

interface Props {
  title: string;
  count?: number;
}

const { title, count = 0 } = Astro.props;
const posts = await getCollection('blog');
---

<!-- Component Template -->
<Header />
<h1>{title}</h1>
<ul>
  {posts.map(post => <li>{post.data.title}</li>)}
</ul>

<style>
  /* Scoped by default */
  h1 { color: blue; }
</style>

<style is:global>
  /* Global styles */
</style>

Pages & Routing

File-based routing from src/pages/:

FileRoute
index.astro/
about.astro/about
blog/[slug].astro/blog/:slug
[...path].astrocatch-all

Dynamic Routes (SSG)

---
// src/pages/posts/[slug].astro
export function getStaticPaths() {
  return [
    { params: { slug: 'post-1' }, props: { title: 'First' } },
    { params: { slug: 'post-2' }, props: { title: 'Second' } },
  ];
}

const { slug } = Astro.params;
const { title } = Astro.props;
---
<h1>{title}</h1>

Layouts

---
// src/layouts/BaseLayout.astro
interface Props {
  title: string;
}
const { title } = Astro.props;
---
<html lang="en">
  <head>
    <title>{title}</title>
  </head>
  <body>
    <slot /> <!-- Child content injected here -->
  </body>
</html>

Usage:

---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="Home">
  <h1>Welcome</h1>
</BaseLayout>

Content Collections

Define in src/content.config.ts:

import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    pubDate: z.coerce.date(),
    draft: z.boolean().optional(),
  }),
});

export const collections = { blog };

Query collections:

---
import { getCollection, getEntry, render } from 'astro:content';

const posts = await getCollection('blog', ({ data }) => !data.draft);
const post = await getEntry('blog', 'my-post');
const { Content } = await render(post);
---
<Content />

UI Framework Islands

Add framework support:

# npm
npx astro add react    # React 19 support
npx astro add vue      # Vue 3
npx astro add svelte   # Svelte 5
npx astro add solid    # SolidJS
npx astro add preact   # Preact

# bun
bunx astro add react vue svelte  # Can add multiple at once

Use client:* directives for hydration:

---
import Counter from './Counter.jsx';
---
<!-- Static by default (no JS) -->
<Counter />

<!-- Hydrated on page load -->
<Counter client:load />

<!-- Hydrated when visible -->
<Counter client:visible />

<!-- Hydrated on idle -->
<Counter client:idle />

<!-- Hydrated on media query -->
<Counter client:media="(max-width: 768px)" />

Server-Side Rendering (SSR)

Enable on-demand rendering:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  output: 'server', // or 'static' (default)
  adapter: node({ mode: 'standalone' }),
});

Per-page opt-in/out:

---
export const prerender = false; // Render on-demand
// export const prerender = true; // Pre-render at build
---

Access request data:

---
const cookie = Astro.cookies.get('session');
const url = Astro.url;
const headers = Astro.request.headers;
---

Server Islands

Defer component rendering until content is ready:

---
import Avatar from './Avatar.astro';
---
<Avatar server:defer>
  <div slot="fallback">Loading...</div>
</Avatar>

Actions

Type-safe backend functions in src/actions/index.ts:

import { defineAction, ActionError } from 'astro:actions';
import { z } from 'astro/zod';

export const server = {
  subscribe: defineAction({
    accept: 'form',
    input: z.object({
      email: z.string().email(),
    }),
    handler: async ({ email }, ctx) => {
      if (!ctx.cookies.has('session')) {
        throw new ActionError({ code: 'UNAUTHORIZED' });
      }
      // Process subscription
      return { success: true };
    },
  }),
};

Call from client:

<script>
import { actions } from 'astro:actions';

const { data, error } = await actions.subscribe({ email: 'test@example.com' });
</script>

View Transitions

Enable SPA-like navigation:

---
import { ClientRouter } from 'astro:transitions';
---
<head>
  <ClientRouter />
</head>

<!-- Animate elements -->
<div transition:animate="slide">
<img transition:name="hero" transition:persist />

Images

---
import { Image, Picture } from 'astro:assets';
import myImage from '../assets/hero.png';
---
<Image src={myImage} alt="Hero" />
<Image src="/public-image.jpg" alt="Public" width={800} height={600} />
<Picture src={myImage} formats={['avif', 'webp']} alt="Hero" />

Styling

<style>
  /* Scoped to component */
  h1 { color: red; }
</style>

<style is:global>
  /* Global styles */
</style>

<style define:vars={{ color: 'blue' }}>
  h1 { color: var(--color); }
</style>

Tailwind CSS v4

npx astro add tailwind
bunx astro add tailwind

MDX Support

npx astro add mdx
bunx astro add mdx

Then use .mdx files in content collections or pages:

---
title: My Post
---
import MyComponent from '../components/MyComponent.astro';

# Hello {props.title}

<MyComponent client:load />

Configuration

// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  site: 'https://example.com',
  base: '/docs',
  output: 'static', // 'static' | 'server'
  trailingSlash: 'always', // 'always' | 'never' | 'ignore'
  integrations: [],
  vite: {},
});

Common Patterns

API Endpoints

// src/pages/api/users.ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ params, request }) => {
  return new Response(JSON.stringify({ users: [] }), {
    headers: { 'Content-Type': 'application/json' },
  });
};

export const POST: APIRoute = async ({ request }) => {
  const data = await request.json();
  return new Response(JSON.stringify({ success: true }));
};

Data Fetching

---
const response = await fetch('https://api.example.com/data');
const data = await response.json();
---

Error Pages

Create src/pages/404.astro and src/pages/500.astro.

Redirects

// astro.config.mjs
export default defineConfig({
  redirects: {
    '/old': '/new',
    '/blog/[...slug]': '/articles/[...slug]',
  },
});

Common Integrations

# All-in-one: React + Tailwind + MDX
bunx astro add react tailwind mdx

# SSR adapters
bunx astro add node       # Node.js standalone
bunx astro add vercel     # Vercel
bunx astro add netlify    # Netlify
bunx astro add cloudflare # Cloudflare Workers

Key References

Additional Resources

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

nextjs

No summary provided by upstream source.

Repository SourceNeeds Review
General

bunjs

No summary provided by upstream source.

Repository SourceNeeds Review
General

mermaid-charts

No summary provided by upstream source.

Repository SourceNeeds Review
General

performance

No summary provided by upstream source.

Repository SourceNeeds Review