astro-developer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Astro Developer Skill

Astro开发者技能

Overview

概述

Enables comprehensive Astro web development including component creation, project setup, configuration optimization, islands architecture implementation, content collections management, and deployment strategies. This skill emphasizes Tailwind CSS-first development for consistent, maintainable styling.
支持全面的Astro Web开发,包括组件创建、项目搭建、配置优化、Islands架构实现、内容集合管理以及部署策略。本技能强调以Tailwind CSS优先的开发方式,以实现一致、可维护的样式设计。

Quick Start

快速开始

Identify the task type and follow the corresponding workflow:
  1. New Project Setup → Use "Project Initialization" workflow
  2. Component Development → Use "Component Creation" guidelines with Tailwind CSS
  3. Testing Setup → See Testing Guide for Vitest/Playwright
  4. Performance Optimization → Use "Islands Architecture" patterns, see Performance Guide
  5. State Management → See State Management Guide for React islands
  6. Troubleshooting Issues → See Common Pitfalls Guide
  7. Content Management → Use "Content Collections" workflow
  8. Configuration & Deployment → Use "Configuration" and "Deployment" sections
识别任务类型并遵循相应工作流程:
  1. 新项目搭建 → 使用「项目初始化」工作流程
  2. 组件开发 → 遵循结合Tailwind CSS的「组件创建」指南
  3. 测试设置 → 查看测试指南了解Vitest/Playwright的使用
  4. 性能优化 → 使用「Islands架构」模式,查看性能指南
  5. 状态管理 → 查看状态管理指南了解React islands的实现
  6. 问题排查 → 查看常见问题指南
  7. 内容管理 → 使用「内容集合」工作流程
  8. 配置与部署 → 参考「配置」和「部署」章节

Core Capabilities

核心能力

1. Project Initialization & Setup

1. 项目初始化与搭建

Create new Astro projects with optimal configurations:
bash
undefined
创建配置优化的Astro新项目:
bash
undefined

Basic Astro project

基础Astro项目

npm create astro@latest my-project
npm create astro@latest my-project

With specific integrations

带特定集成

npm create astro@latest -- --add react --add tailwind --add mdx
npm create astro@latest -- --add react --add tailwind --add mdx

From template

从模板创建

npm create astro@latest -- --template blog

Essential project structure to create:
src/ ├── components/ # Reusable Astro/UI framework components ├── layouts/ # Page layout templates ├── pages/ # File-based routing (REQUIRED) ├── styles/ # CSS/Sass files ├── content/ # Content collections (Markdown/MDX) └── env.d.ts # TypeScript environment types public/ # Static assets (robots.txt, favicon, etc) astro.config.mjs # Astro configuration tsconfig.json # TypeScript configuration package.json # Project dependencies and scripts
undefined
npm create astro@latest -- --template blog

需创建的核心项目结构:
src/ ├── components/ # 可复用的Astro/UI框架组件 ├── layouts/ # 页面布局模板 ├── pages/ # 文件式路由(必填) ├── styles/ # CSS/Sass文件 ├── content/ # 内容集合(Markdown/MDX) └── env.d.ts # TypeScript环境类型 public/ # 静态资源(robots.txt、favicon等) astro.config.mjs # Astro配置文件 tsconfig.json # TypeScript配置文件 package.json # 项目依赖与脚本
undefined

2. Component Creation

2. 组件创建

Astro Components (.astro)

Astro组件(.astro)

Create server-rendered components with zero client-side JavaScript and Tailwind CSS styling:
astro
---
// Component frontmatter - runs on server only
import { SITE_TITLE } from '@/config';
export interface Props {
  title?: string;
  published?: Date;
  variant?: 'default' | 'primary' | 'secondary';
}

const { title, published, variant = 'default' } = Astro.props;

const variantClasses = {
  default: 'bg-white dark:bg-gray-800',
  primary: 'bg-blue-500 dark:bg-blue-600 text-white',
  secondary: 'bg-gray-100 dark:bg-gray-700'
};
---

<!-- Component template - HTML with special syntax -->
<html lang="en" class="h-full">
  <head>
    <title>{title || SITE_TITLE}</title>
  </head>
  <body class="h-full m-0 font-sans leading-relaxed text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-900">
    <main class={`${variantClasses[variant]} p-6 rounded-lg shadow-sm`}>
      {title && <h1 class="text-2xl font-bold mb-4">{title}</h1>}
      {published && (
        <time class="text-sm text-gray-600 dark:text-gray-400">
          {published.toLocaleDateString()}
        </time>
      )}
      <slot />  <!-- Children content -->
    </main>
  </body>
</html>
创建零客户端JavaScript的服务端渲染组件,并结合Tailwind CSS样式:
astro
---
// 组件前置代码 - 仅在服务端运行
import { SITE_TITLE } from '@/config';
export interface Props {
  title?: string;
  published?: Date;
  variant?: 'default' | 'primary' | 'secondary';
}

const { title, published, variant = 'default' } = Astro.props;

const variantClasses = {
  default: 'bg-white dark:bg-gray-800',
  primary: 'bg-blue-500 dark:bg-blue-600 text-white',
  secondary: 'bg-gray-100 dark:bg-gray-700'
};
---

<!-- 组件模板 - 带特殊语法的HTML -->
<html lang="en" class="h-full">
  <head>
    <title>{title || SITE_TITLE}</title>
  </head>
  <body class="h-full m-0 font-sans leading-relaxed text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-900">
    <main class={`${variantClasses[variant]} p-6 rounded-lg shadow-sm`}>
      {title && <h1 class="text-2xl font-bold mb-4">{title}</h1>}
      {published && (
        <time class="text-sm text-gray-600 dark:text-gray-400">
          {published.toLocaleDateString()}
        </time>
      )}
      <slot />  <!-- 子内容插槽 -->
    </main>
  </body>
</html>

UI Framework Components (React, Vue, Svelte)

UI框架组件(React、Vue、Svelte)

Add interactivity with client directives:
astro
---
import ReactCounter from '@/components/ReactCounter.jsx';
import VueComponent from '@/components/VueComponent.vue';
import SvelteButton from '@/components/SvelteButton.svelte';
---

<!-- Load immediately -->
<ReactCounter client:load />

<!-- Load when visible in viewport -->
<SvelteButton client:visible />

<!-- Load when browser is idle -->
<VueComponent client:idle />

<!-- Load only on mobile -->
<ReactCounter client:load media="(max-width: 768px)" />
通过客户端指令添加交互性:
astro
---
import ReactCounter from '@/components/ReactCounter.jsx';
import VueComponent from '@/components/VueComponent.vue';
import SvelteButton from '@/components/SvelteButton.svelte';
---

<!-- 立即加载 -->
<ReactCounter client:load />

<!-- 进入视口时加载 -->
<SvelteButton client:visible />

<!-- 浏览器空闲时加载 -->
<VueComponent client:idle />

<!-- 仅在移动端加载 -->
<ReactCounter client:load media="(max-width: 768px)" />

3. Islands Architecture

3. Islands架构

Implement optimal performance with selective hydration:
通过选择性水合实现最优性能:

Client Islands Strategy

客户端Islands策略

  1. Identify interactive components - Carousels, forms, modals
  2. Choose appropriate client directive:
    • client:load
      - Immediately (headers, critical features)
    • client:idle
      - When browser free (secondary features)
    • client:visible
      - When scrolled to (below-fold content)
    • client:media
      - Based on media query
astro
---
import InteractiveHeader from '@/components/InteractiveHeader.astro';
import ImageCarousel from '@/components/ImageCarousel.jsx';
import NewsletterForm from '@/components/NewsletterForm.jsx';
import SocialShare from '@/components/SocialShare.jsx';
---

<!-- Above fold, critical interactivity -->
<InteractiveHeader client:load />

<!-- Content heavy, load when visible -->
<ImageCarousel client:visible />

<!-- Secondary feature, load when idle -->
<NewsletterForm client:idle />

<!-- Mobile-only interactivity -->
<SocialShare client:load media="(max-width: 768px)" />
  1. 识别交互式组件 - 轮播图、表单、模态框
  2. 选择合适的客户端指令
    • client:load
      - 立即加载(页头、核心功能)
    • client:idle
      - 浏览器空闲时加载(次要功能)
    • client:visible
      - 滚动到视图时加载(折叠下方内容)
    • client:media
      - 基于媒体查询加载
astro
---
import InteractiveHeader from '@/components/InteractiveHeader.astro';
import ImageCarousel from '@/components/ImageCarousel.jsx';
import NewsletterForm from '@/components/NewsletterForm.jsx';
import SocialShare from '@/components/SocialShare.jsx';
---

<!-- 首屏区域,核心交互 -->
<InteractiveHeader client:load />

<!-- 内容密集,进入视口时加载 -->
<ImageCarousel client:visible />

<!-- 次要功能,浏览器空闲时加载 -->
<NewsletterForm client:idle />

<!-- 仅移动端交互 -->
<SocialShare client:load media="(max-width: 768px)" />

Server Islands for Dynamic Content

服务端Islands用于动态内容

Use
server:defer
for personalized/dynamic content:
astro
---
import UserProfile from '@/components/UserProfile.astro';
import RecommendedPosts from '@/components/RecommendedPosts.astro';
---

<!-- Static content loads immediately -->
<main>
  <h1>Welcome to our blog</h1>
  <p>Explore our latest articles...</p>
</main>

<!-- Dynamic content loads in parallel -->
<aside>
  <!-- User's profile with personalized data -->
  <UserProfile server:defer />

  <!-- Recommended posts based on history -->
  <RecommendedPosts server:defer />
</aside>
使用
server:defer
加载个性化/动态内容:
astro
---
import UserProfile from '@/components/UserProfile.astro';
import RecommendedPosts from '@/components/RecommendedPosts.astro';
---

<!-- 静态内容立即加载 -->
<main>
  <h1>欢迎访问我们的博客</h1>
  <p>探索我们的最新文章...</p>
</main>

<!-- 动态内容并行加载 -->
<aside>
  <!-- 带个性化数据的用户资料 -->
  <UserProfile server:defer />

  <!-- 基于浏览历史的推荐文章 -->
  <RecommendedPosts server:defer />
</aside>

4. Routing & Pages

4. 路由与页面

File-Based Routing

文件式路由

Create pages using Astro's file-based routing:
src/pages/
├── index.astro           # → /
├── about.astro           # → /about
├── blog/
│   ├── index.astro       # → /blog
│   ├── [slug].astro      # → /blog/post-title
│   └── [...page].astro   # → /blog/2, /blog/3
└── api/
    └── posts.json.js     # → /api/posts (API endpoint)
使用Astro的文件式路由创建页面:
src/pages/
├── index.astro           # → /
├── about.astro           # → /about
├── blog/
│   ├── index.astro       # → /blog
│   ├── [slug].astro      # → /blog/post-title
│   └── [...page].astro   # → /blog/2, /blog/3
└── api/
    └── posts.json.js     # → /api/posts(API端点)

Dynamic Routes

动态路由

Handle dynamic segments with params:
astro
---
// 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 { Content, frontmatter } = Astro.props;
---

<h1>{frontmatter.title}</h1>
<p>Published: {frontmatter.pubDate.toLocaleDateString()}</p>
<Content />
通过参数处理动态路由片段:
astro
---
// 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 { Content, frontmatter } = Astro.props;
---

<h1>{frontmatter.title}</h1>
<p>发布时间:{frontmatter.pubDate.toLocaleDateString()}</p>
<Content />

API Routes

API路由

Create server endpoints:
javascript
// src/pages/api/posts.json.js
export async function GET() {
  return Response.json({
    posts: [
      { id: 1, title: "First post" },
      { id: 2, title: "Second post" },
    ],
  });
}

export async function POST({ request }) {
  const data = await request.json();
  // Process form submission
  return Response.json({ success: true });
}
创建服务端端点:
javascript
// src/pages/api/posts.json.js
export async function GET() {
  return Response.json({
    posts: [
      { id: 1, title: "第一篇文章" },
      { id: 2, title: "第二篇文章" },
    ],
  });
}

export async function POST({ request }) {
  const data = await request.json();
  // 处理表单提交
  return Response.json({ success: true });
}

5. Content Collections

5. 内容集合

Organize and validate content with type safety:
通过类型安全的方式组织和验证内容:

Configure Collections

配置内容集合

typescript
// src/content/config.ts
import { defineCollection, z } from "astro:content";

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    updatedDate: z.date().optional(),
    description: z.string(),
    heroImage: z.string().optional(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
  }),
});

const projects = defineCollection({
  schema: z.object({
    title: z.string(),
    description: z.string(),
    startDate: z.date(),
    endDate: z.date().optional(),
    technologies: z.array(z.string()),
    demoUrl: z.string().url().optional(),
    repoUrl: z.string().url().optional(),
  }),
});

export const collections = { blog, projects };
typescript
// src/content/config.ts
import { defineCollection, z } from "astro:content";

const blog = defineCollection({
  schema: z.object({
    title: z.string(),
    pubDate: z.date(),
    updatedDate: z.date().optional(),
    description: z.string(),
    heroImage: z.string().optional(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
  }),
});

const projects = defineCollection({
  schema: z.object({
    title: z.string(),
    description: z.string(),
    startDate: z.date(),
    endDate: z.date().optional(),
    technologies: z.array(z.string()),
    demoUrl: z.string().url().optional(),
    repoUrl: z.string().url().optional(),
  }),
});

export const collections = { blog, projects };

Use Content in Pages

在页面中使用内容

astro
---
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';
import BlogLayout from '@/layouts/BlogLayout.astro';
import BlogPost from '@/components/BlogPost.astro';

const posts = await getCollection('blog', ({ data }) => !data.draft);
const sortedPosts = posts.sort((a, b) =>
  b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);
---

<BlogLayout title="Blog">
  {sortedPosts.map((post) => (
    <BlogPost post={post} />
  ))}
</BlogLayout>
astro
---
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';
import BlogLayout from '@/layouts/BlogLayout.astro';
import BlogPost from '@/components/BlogPost.astro';

const posts = await getCollection('blog', ({ data }) => !data.draft);
const sortedPosts = posts.sort((a, b) =>
  b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);
---

<BlogLayout title="博客">
  {sortedPosts.map((post) => (
    <BlogPost post={post} />
  ))}
</BlogLayout>

6. Styling & Integrations

6. 样式与集成

Tailwind CSS Integration (Primary Styling Approach)

Tailwind CSS集成(主要样式方案)

This skill emphasizes Tailwind CSS as the primary styling solution for all Astro projects.
javascript
// astro.config.mjs
import tailwind from "@astrojs/tailwind";

export default defineConfig({
  integrations: [tailwind()],
});
Configure Tailwind for optimal performance:
javascript
// tailwind.config.js
export default {
  content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
  darkMode: "class", // Enables dark mode with .dark class
  theme: {
    extend: {
      fontFamily: {
        sans: ["Inter", "system-ui", "sans-serif"],
      },
      colors: {
        // Define brand colors
        primary: {
          50: "#eff6ff",
          500: "#3b82f6",
          600: "#2563eb",
          900: "#1e3a8a",
        },
      },
    },
  },
  plugins: [],
};
Global styles setup:
css
/* src/styles/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  /* Custom base styles */
}

@layer components {
  /* Custom component classes */
}
本技能强调将Tailwind CSS作为所有Astro项目的主要样式解决方案。
javascript
// astro.config.mjs
import tailwind from "@astrojs/tailwind";

export default defineConfig({
  integrations: [tailwind()],
});
配置Tailwind以实现最优性能:
javascript
// tailwind.config.js
export default {
  content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
  darkMode: "class", // 通过.dark类启用暗色模式
  theme: {
    extend: {
      fontFamily: {
        sans: ["Inter", "system-ui", "sans-serif"],
      },
      colors: {
        // 定义品牌颜色
        primary: {
          50: "#eff6ff",
          500: "#3b82f6",
          600: "#2563eb",
          900: "#1e3a8a",
        },
      },
    },
  },
  plugins: [],
};
全局样式设置:
css
/* src/styles/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  /* 自定义基础样式 */
}

@layer components {
  /* 自定义组件类 */
}

Tailwind CSS Best Practices

Tailwind CSS最佳实践

  1. Use Custom Brand Colors: Always use the predefined brand colors from
    global.css
    astro
    <!-- ✅ Use brand colors -->
    <div class="bg-mitra-blue text-warm-cream">
    <div class="border-lush-green bg-warm-orange/10">
    
    <!-- ❌ Avoid generic colors -->
    <div class="bg-blue-500 text-yellow-100">
    <div class="border-green-500 bg-orange-100">
    Available brand colors:
    • Primary:
      mitra-blue
      ,
      mitra-yellow
      ,
      lush-green
      ,
      warm-orange
    • Text:
      charcoal-grey
      ,
      warm-cream
    • Gradients:
      bg-magic-gradient
      (custom utility),
      bg-linear-to-br
      with brand colors
  2. Variant-based styling: Use JavaScript objects with brand colors
    javascript
    const buttonVariants = {
      primary: "bg-mitra-blue hover:bg-mitra-blue-dark text-white",
      secondary: "bg-warm-cream hover:bg-grey-100 text-charcoal-grey",
      accent: "bg-warm-orange hover:bg-warm-orange-dark text-white",
    };
  3. Responsive design: Use Tailwind's responsive prefixes
    astro
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  4. Dark mode: Implement with
    dark:
    prefix
    astro
    <div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
  5. Composition: Combine utility classes with brand colors
    astro
    <!-- ✅ Using brand colors -->
    <div class="flex flex-col items-center justify-center p-8 bg-linear-to-br from-mitra-blue/10 to-lush-green/10 rounded-2xl shadow-xl">
    <div class="p-6 border border-warm-orange/20 bg-magic-gradient">
  6. Custom properties: Use CSS variables for dynamic values
    astro
    <div style="--delay: 100ms" class="animate-pulse [--delay:200ms]">
  1. 使用自定义品牌颜色:始终使用
    global.css
    中预定义的品牌颜色
    astro
    <!-- ✅ 推荐:使用品牌颜色 -->
    <div class="bg-mitra-blue text-warm-cream">
    <div class="border-lush-green bg-warm-orange/10">
    
    <!-- ❌ 不推荐:使用通用颜色 -->
    <div class="bg-blue-500 text-yellow-100">
    <div class="border-green-500 bg-orange-100">
    可用品牌颜色:
    • 主色调:
      mitra-blue
      mitra-yellow
      lush-green
      warm-orange
    • 文字色:
      charcoal-grey
      warm-cream
    • 渐变:
      bg-magic-gradient
      (自定义工具类)、结合品牌颜色的
      bg-linear-to-br
  2. 基于变体的样式:使用JavaScript对象结合品牌颜色
    javascript
    const buttonVariants = {
      primary: "bg-mitra-blue hover:bg-mitra-blue-dark text-white",
      secondary: "bg-warm-cream hover:bg-grey-100 text-charcoal-grey",
      accent: "bg-warm-orange hover:bg-warm-orange-dark text-white",
    };
  3. 响应式设计:使用Tailwind的响应式前缀
    astro
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  4. 暗色模式:通过
    dark:
    前缀实现
    astro
    <div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
  5. 样式组合:结合工具类与品牌颜色
    astro
    <!-- ✅ 使用品牌颜色 -->
    <div class="flex flex-col items-center justify-center p-8 bg-linear-to-br from-mitra-blue/10 to-lush-green/10 rounded-2xl shadow-xl">
    <div class="p-6 border border-warm-orange/20 bg-magic-gradient">
  6. 自定义属性:使用CSS变量实现动态值
    astro
    <div style="--delay: 100ms" class="animate-pulse [--delay:200ms]">

6. Tailwind CSS v4 Canonical Class Names

6. Tailwind CSS v4标准类名

IMPORTANT: Tailwind CSS v4 uses different canonical class names. Always use these updated forms:
  • bg-gradient-to-*
    bg-linear-to-*
    (e.g.,
    bg-gradient-to-r
    bg-linear-to-r
    )
  • flex-shrink-0
    shrink-0
  • aspect-[3/2]
    aspect-3/2
    (remove brackets for simple ratios)
  • grayscale-[30%]
    grayscale-30
    (remove brackets for percentage values)
Examples:
astro
<!-- Correct (Tailwind v4) -->
<div class="bg-linear-to-r from-blue-500 to-purple-600 shrink-0 aspect-3/2 grayscale-30">

<!-- Incorrect (deprecated) -->
<!-- These will trigger linter warnings: -->
<!-- bg-gradient-to-r → should be bg-linear-to-r -->
<!-- flex-shrink-0 → should be shrink-0 -->
<!-- aspect-[3/2] → should be aspect-3/2 -->
<!-- grayscale-[30%] → should be grayscale-30 -->
重要提示:Tailwind CSS v4使用不同的标准类名,请始终使用以下更新后的形式:
  • bg-gradient-to-*
    bg-linear-to-*
    (例如:
    bg-gradient-to-r
    bg-linear-to-r
  • flex-shrink-0
    shrink-0
  • aspect-[3/2]
    aspect-3/2
    (简单比例移除方括号)
  • grayscale-[30%]
    grayscale-30
    (百分比值移除方括号)
示例
astro
<!-- 正确(Tailwind v4) -->
<div class="bg-linear-to-r from-blue-500 to-purple-600 shrink-0 aspect-3/2 grayscale-30">

<!-- 错误(已废弃) -->
<!-- 这些会触发代码检查警告: -->
<!-- bg-gradient-to-r → 应改为bg-linear-to-r -->
<!-- flex-shrink-0 → 应改为shrink-0 -->
<!-- aspect-[3/2] → 应改为aspect-3/2 -->
<!-- grayscale-[30%] → 应改为grayscale-30 -->

React Integration

React集成

javascript
// astro.config.mjs
import react from "@astrojs/react";

export default defineConfig({
  integrations: [react()],
});
javascript
// astro.config.mjs
import react from "@astrojs/react";

export default defineConfig({
  integrations: [react()],
});

MDX Integration

MDX集成

javascript
// astro.config.mjs
import mdx from "@astrojs/mdx";

export default defineConfig({
  integrations: [mdx()],
});
javascript
// astro.config.mjs
import mdx from "@astrojs/mdx";

export default defineConfig({
  integrations: [mdx()],
});

7. Performance Optimization

7. 性能优化

Image Optimization

图片优化

astro
---
import { Image } from 'astro:assets';
import heroImage from '@/images/hero.jpg';
---

<!-- Optimized, responsive images -->
<Image
  src={heroImage}
  alt="Hero section background"
  widths={[400, 800, 1200]}
  formats={['avif', 'webp', 'jpg']}
  loading="eager"
/>
astro
---
import { Image } from 'astro:assets';
import heroImage from '@/images/hero.jpg';
---

<!-- 经过优化的响应式图片 -->
<Image
  src={heroImage}
  alt="首页横幅背景"
  widths={[400, 800, 1200]}
  formats={['avif', 'webp', 'jpg']}
  loading="eager"
/>

View Transitions

视图过渡

Enable smooth page transitions:
astro
---
// src/layouts/MainLayout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html>
  <head>
    <ViewTransitions />
  </head>
  <body>
    <header>
      <nav>
        <a href="/" transition:name="home">Home</a>
        <a href="/about" transition:name="about">About</a>
      </nav>
    </header>
    <main transition:name="main-content">
      <slot />
    </main>
  </body>
</html>
启用流畅的页面过渡效果:
astro
---
// src/layouts/MainLayout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html>
  <head>
    <ViewTransitions />
  </head>
  <body>
    <header>
      <nav>
        <a href="/" transition:name="home">首页</a>
        <a href="/about" transition:name="about">关于我们</a>
      </nav>
    </header>
    <main transition:name="main-content">
      <slot />
    </main>
  </body>
</html>

8. Configuration Best Practices

8. 配置最佳实践

Optimize astro.config.mjs

优化astro.config.mjs

javascript
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap";
import tailwind from "@astrojs/tailwind";

export default defineConfig({
  // Site metadata for SEO
  site: "https://yoursite.com",
  base: "/subpath", // If deploying to subdirectory

  // Integrations
  integrations: [react(), tailwind(), sitemap()],

  // Build optimizations
  build: {
    format: "directory", // Clean URLs
    assets: "_assets", // Custom assets path
  },

  // Vite configurations
  vite: {
    optimizeDeps: {
      exclude: ["some-large-package"],
    },
  },

  // Server options for SSR
  output: "hybrid", // or 'server' or 'static'

  // Security headers
  security: {
    allowedHosts: ["yoursite.com"],
  },
});
javascript
import { defineConfig } from "astro/config";
import react from "@astrojs/react";
import sitemap from "@astrojs/sitemap";
import tailwind from "@astrojs/tailwind";

export default defineConfig({
  // SEO用站点元数据
  site: "https://yoursite.com",
  base: "/subpath", // 若部署到子目录

  // 集成插件
  integrations: [react(), tailwind(), sitemap()],

  // 构建优化
  build: {
    format: "directory", // 干净URL
    assets: "_assets", // 自定义资源路径
  },

  // Vite配置
  vite: {
    optimizeDeps: {
      exclude: ["some-large-package"],
    },
  },

  // SSR用服务器选项
  output: "hybrid", // 或'server'、'static'

  // 安全头
  security: {
    allowedHosts: ["yoursite.com"],
  },
});

TypeScript Configuration

TypeScript配置

json
// tsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/layouts/*": ["./src/layouts/*"]
    },
    "types": ["@astrojs/image/client"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts"]
}
json
// tsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/layouts/*": ["./src/layouts/*"]
    },
    "types": ["@astrojs/image/client"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts"]
}

9. Deployment Strategies

9. 部署策略

Static Site Generation (Default)

静态站点生成(默认)

bash
npm run build  # Creates static files in dist/
Deploy to:
  • Vercel, Netlify, Cloudflare Pages
  • GitHub Pages, GitLab Pages
  • Any static hosting
bash
npm run build  # 在dist/目录生成静态文件
可部署至:
  • Vercel、Netlify、Cloudflare Pages
  • GitHub Pages、GitLab Pages
  • 任何静态托管平台

Hybrid Rendering

混合渲染

javascript
// astro.config.mjs
export default defineConfig({
  output: 'hybrid',
});

// Individual pages can opt-in to SSR
---
export const prerender = false;
---
javascript
// astro.config.mjs
export default defineConfig({
  output: 'hybrid',
});

// 单个页面可选择启用SSR
---
export const prerender = false;
---

Server-Side Rendering

服务端渲染

javascript
// astro.config.mjs
export default defineConfig({
  output: "server",
  adapter: node({
    mode: "standalone",
  }),
});
Deploy to:
  • Node.js servers
  • Docker containers
  • Serverless platforms (Vercel, Netlify Functions)
javascript
// astro.config.mjs
export default defineConfig({
  output: "server",
  adapter: node({
    mode: "standalone",
  }),
});
可部署至:
  • Node.js服务器
  • Docker容器
  • 无服务器平台(Vercel、Netlify Functions)

10. Testing Strategies

10. 测试策略

See Testing Guide for comprehensive testing documentation.
查看测试指南获取全面的测试文档。

Vitest for Unit Testing

Vitest单元测试

bash
npm install -D vitest @vitest/ui jsdom
typescript
// vitest.config.ts
import { getViteConfig } from 'astro/config';

export default getViteConfig({
  test: {
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,ts,jsx,tsx}'],
  },
});
bash
npm install -D vitest @vitest/ui jsdom
typescript
// vitest.config.ts
import { getViteConfig } from 'astro/config';

export default getViteConfig({
  test: {
    environment: 'jsdom',
    include: ['src/**/*.{test,spec}.{js,ts,jsx,tsx}'],
  },
});

Playwright for E2E Testing

Playwright端到端测试

bash
npm init playwright@latest
typescript
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  webServer: {
    command: 'npm run preview',
    url: 'http://localhost:4321/',
  },
});
bash
npm init playwright@latest
typescript
// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  webServer: {
    command: 'npm run preview',
    url: 'http://localhost:4321/',
  },
});

Container API for Astro Components

Astro组件的容器API

javascript
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import { expect, test } from 'vitest';
import Card from '../src/components/Card.astro';

test('Card renders with props', async () => {
  const container = await AstroContainer.create();
  const result = await container.renderToString(Card, {
    props: { title: 'Test' },
  });
  expect(result).toContain('Test');
});
javascript
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import { expect, test } from 'vitest';
import Card from '../src/components/Card.astro';

test('Card组件可根据props渲染', async () => {
  const container = await AstroContainer.create();
  const result = await container.renderToString(Card, {
    props: { title: '测试' },
  });
  expect(result).toContain('测试');
});

11. TypeScript Best Practices

11. TypeScript最佳实践

See Common Pitfalls Guide for TypeScript-specific issues.
查看常见问题指南获取TypeScript相关问题的解决方案。

Strict Mode Configuration

严格模式配置

json
// tsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/layouts/*": ["./src/layouts/*"]
    }
  }
}
json
// tsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/layouts/*": ["./src/layouts/*"]
    }
  }
}

Type-Safe Props

类型安全的Props

astro
---
export interface Props {
  title: string;
  count: number;
  isActive?: boolean;
  tags: string[];
}

const { title, count, isActive = false, tags } = Astro.props;
---
astro
---
export interface Props {
  title: string;
  count: number;
  isActive?: boolean;
  tags: string[];
}

const { title, count, isActive = false, tags } = Astro.props;
---

12. State Management for React Islands

12. React Islands的状态管理

See State Management Guide for comprehensive patterns.
查看状态管理指南获取全面的实现模式。

Zustand (Recommended)

Zustand(推荐)

typescript
// src/store/useStore.ts
import { create } from 'zustand';

export const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));
typescript
// src/store/useStore.ts
import { create } from 'zustand';

export const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));

Usage Across Islands

跨Islands使用

jsx
// Component 1
import { useStore } from '@/store/useStore';

function Counter() {
  const { increment } = useStore();
  return <button onClick={increment}>+</button>;
}

// Component 2
import { useStore } from '@/store/useStore';

function Display() {
  const count = useStore((state) => state.count);
  return <div>{count}</div>;
}
jsx
// 组件1
import { useStore } from '@/store/useStore';

function Counter() {
  const { increment } = useStore();
  return <button onClick={increment}>+</button>;
}

// 组件2
import { useStore } from '@/store/useStore';

function Display() {
  const count = useStore((state) => state.count);
  return <div>{count}</div>;
}

Common Patterns & Solutions

常见模式与解决方案

Environment Variables

环境变量

typescript
// Create .env file
PUBLIC_API_URL=https://api.example.com
SECRET_KEY=your-secret-key

// Use in components
const apiUrl = import.meta.env.PUBLIC_API_URL;
typescript
// 创建.env文件
PUBLIC_API_URL=https://api.example.com
SECRET_KEY=your-secret-key

// 在组件中使用
const apiUrl = import.meta.env.PUBLIC_API_URL;

SEO Best Practices

SEO最佳实践

astro
---
// src/layouts/BaseLayout.astro
interface Props {
  title: string;
  description: string;
  image?: string;
  url?: string;
}

const { title, description, image, url } = Astro.props;
const siteUrl = Astro.site;
const canonicalUrl = url ? new URL(url, siteUrl) : siteUrl;
---

<html>
  <head>
    <title>{title}</title>
    <meta name="description" content={description} />
    <link rel="canonical" href={canonicalUrl} />

    {image && (
      <meta property="og:image" content={new URL(image, siteUrl)} />
    )}

    <meta property="og:title" content={title} />
    <meta property="og:description" content={description} />
    <meta property="og:url" content={canonicalUrl} />
    <meta name="twitter:card" content="summary_large_image" />
  </head>
</html>
astro
---
// src/layouts/BaseLayout.astro
interface Props {
  title: string;
  description: string;
  image?: string;
  url?: string;
}

const { title, description, image, url } = Astro.props;
const siteUrl = Astro.site;
const canonicalUrl = url ? new URL(url, siteUrl) : siteUrl;
---

<html>
  <head>
    <title>{title}</title>
    <meta name="description" content={description} />
    <link rel="canonical" href={canonicalUrl} />

    {image && (
      <meta property="og:image" content={new URL(image, siteUrl)} />
    )}

    <meta property="og:title" content={title} />
    <meta property="og:description" content={description} />
    <meta property="og:url" content={canonicalUrl} />
    <meta name="twitter:card" content="summary_large_image" />
  </head>
</html>

Error Handling

错误处理

astro
---
// src/pages/404.astro
import Layout from '@/layouts/Layout.astro';
---

<Layout title="Not Found">
  <h1>404 - Page not found</h1>
  <p>Sorry, we couldn't find that page.</p>
</Layout>
javascript
// src/pages/error/[...code].astro
export function getStaticPaths() {
  return [{ params: { code: "403" } }, { params: { code: "500" } }];
}

const { code } = Astro.params;
const errorMessages = {
  403: "Forbidden",
  500: "Internal Server Error",
};
astro
---
// src/pages/404.astro
import Layout from '@/layouts/Layout.astro';
---

<Layout title="页面未找到">
  <h1>404 - 页面未找到</h1>
  <p>抱歉,我们无法找到您访问的页面。</p>
</Layout>
javascript
// src/pages/error/[...code].astro
export function getStaticPaths() {
  return [{ params: { code: "403" } }, { params: { code: "500" } }];
}

const { code } = Astro.params;
const errorMessages = {
  403: "禁止访问",
  500: "服务器内部错误",
};

Common Issues & Solutions

常见问题与解决方案

Component Not Interactive

组件无交互性

Problem: React/Vue components render but don't respond to user interaction.
Solution: Add
client:*
directive. By default, Astro strips all client-side JavaScript.
astro
---
import ReactComponent from '@/components/ReactComponent.jsx';
---

<!-- ❌ Wrong: No client directive -->
<ReactComponent />

<!-- ✅ Correct: Add appropriate client directive -->
<ReactComponent client:load />
问题:React/Vue组件可渲染,但无法响应用户交互。
解决方案:添加
client:*
指令。默认情况下,Astro会移除所有客户端JavaScript。
astro
---
import ReactComponent from '@/components/ReactComponent.jsx';
---

<!-- ❌ 错误:无客户端指令 -->
<ReactComponent />

<!-- ✅ 正确:添加合适的客户端指令 -->
<ReactComponent client:load />

Context API Not Working Across Islands

Context API在跨Islands间不生效

Problem: React Context providers don't share state between different component islands.
Solution: Each Astro island hydrates in isolation. Use external state management (Zustand, Redux, MobX) for cross-island state sharing.
See State Management Guide for detailed patterns.
问题:React Context提供者无法在不同组件Islands间共享状态。
解决方案:每个Astro Island都是独立水合的。使用外部状态管理工具(Zustand、Redux、MobX)实现跨Islands状态共享。
查看状态管理指南获取详细实现模式。

document
or
window
is Not Defined

document
window
未定义

Problem: Error accessing browser APIs during server-side rendering.
Solution: Move browser-only code to
<script>
tags or use lifecycle methods in framework components.
astro
---
// ❌ Wrong: Browser API in frontmatter
const width = window.innerWidth;
---

<!-- ✅ Correct: Move to script tag -->
<script>
  const width = window.innerWidth;
</script>
问题:服务端渲染期间访问浏览器API时出现错误。
解决方案:将仅浏览器端代码移至
<script>
标签中,或在框架组件中使用生命周期方法。
astro
---
// ❌ 错误:在前置代码中使用浏览器API
const width = window.innerWidth;
---

<!-- ✅ 正确:移至script标签 -->
<script>
  const width = window.innerWidth;
</script>

TypeScript Ref Callback Errors

TypeScript Ref回调错误

When using React refs with arrays in TypeScript, avoid this common error:
tsx
// ❌ Incorrect - TypeScript error
<div ref={(el) => (cardsRef.current[index] = el)}>

// ✅ Correct - Wrap the assignment
<div ref={(el) => {
  cardsRef.current[index] = el;
}}>
在TypeScript中使用React refs数组时,避免以下常见错误:
tsx
// ❌ 错误 - TypeScript报错
<div ref={(el) => (cardsRef.current[index] = el)}>

// ✅ 正确 - 包裹赋值操作
<div ref={(el) => {
  cardsRef.current[index] = el;
}}>

Tailwind CSS v4 Migration

Tailwind CSS v4迁移

Common issues when migrating from Tailwind CSS v3 to v4:
  1. Gradient classes: Always use
    bg-linear-to-*
    instead of
    bg-gradient-to-*
  2. Aspect ratios: Use
    aspect-3/2
    instead of
    aspect-[3/2]
    for simple ratios
  3. Flexbox: Use
    shrink-0
    instead of
    flex-shrink-0
  4. Filters: Use
    grayscale-30
    instead of
    grayscale-[30%]
    for percentage values
从Tailwind CSS v3迁移至v4时的常见问题:
  1. 渐变类:始终使用
    bg-linear-to-*
    而非
    bg-gradient-to-*
  2. 宽高比:简单比例使用
    aspect-3/2
    而非
    aspect-[3/2]
  3. Flexbox:使用
    shrink-0
    而非
    flex-shrink-0
  4. 滤镜:百分比值使用
    grayscale-30
    而非
    grayscale-[30%]

File Path Resolution

文件路径解析

If you encounter errors about missing files that should exist:
  1. Check if the file exists at the expected path
  2. The error might be from an outdated diagnostic cache
  3. Files may have been renamed or moved
若遇到文件存在但提示缺失的错误:
  1. 检查文件是否存在于预期路径
  2. 错误可能来自过时的诊断缓存
  3. 文件可能已被重命名或移动

Resources

资源

scripts/

scripts/

The scripts/ directory contains automation utilities:
  • create-component.js
    - Generates component boilerplate
  • optimize-images.js
    - Batch image optimization
  • generate-sitemap.js
    - Custom sitemap generation
Execute scripts without loading into context:
bash
node scripts/create-component.js --name MyComponent --type astro
scripts/目录包含自动化工具:
  • create-component.js
    - 生成组件模板代码
  • optimize-images.js
    - 批量图片优化
  • generate-sitemap.js
    - 自定义站点地图生成
无需加载上下文即可执行脚本:
bash
node scripts/create-component.js --name MyComponent --type astro

references/

references/

Reference materials for detailed information:
  • component-patterns.md
    - Common Astro component patterns
  • integration-guide.md
    - Detailed integration setup guides (React, Vue, Tailwind, MDX, etc.)
  • testing-guide.md
    - NEW: Comprehensive testing strategies with Vitest, Playwright, and Container API
  • common-pitfalls.md
    - NEW: Common mistakes and solutions for islands architecture, client directives, SSR vs static rendering
  • performance-optimization.md
    - NEW: Build optimization, image optimization, code splitting, deployment strategies
  • state-management.md
    - NEW: State management patterns for React islands (Zustand, Redux Toolkit, Jotai, TanStack Query)
Load reference materials when specific detailed information is needed:
Read references/testing-guide.md when setting up testing infrastructure
Read references/common-pitfalls.md when troubleshooting hydration or directive issues
Read references/performance-optimization.md when optimizing build size or load times
Read references/state-management.md when implementing cross-island state sharing
参考资料提供详细信息:
  • component-patterns.md
    - 常见Astro组件模式
  • integration-guide.md
    - 详细的集成设置指南(React、Vue、Tailwind、MDX等)
  • testing-guide.md
    - 新增:结合Vitest、Playwright和容器API的全面测试策略
  • common-pitfalls.md
    - 新增:Islands架构、客户端指令、SSR与静态渲染的常见错误及解决方案
  • performance-optimization.md
    - 新增:构建优化、图片优化、代码分割、部署策略
  • state-management.md
    - 新增:React Islands的状态管理模式(Zustand、Redux Toolkit、Jotai、TanStack Query)
需要特定详细信息时加载参考资料:
设置测试基础设施时,阅读references/testing-guide.md
排查水合或指令问题时,阅读references/common-pitfalls.md
优化构建体积或加载速度时,阅读references/performance-optimization.md
实现跨Islands状态共享时,阅读references/state-management.md

assets/

assets/

Templates and boilerplate code:
  • component-templates/
    - Starting templates for different component types
  • layout-templates/
    - Common layout patterns
  • page-templates/
    - Page boilerplate for different use cases
Use assets as starting points:
  • Copy component templates for new components
  • Reference layout templates for consistent structure
  • Adapt page templates for common page types

This skill provides comprehensive Astro development guidance from project setup through deployment optimization.
模板与样板代码:
  • component-templates/
    - 不同组件类型的起始模板
  • layout-templates/
    - 常见布局模式
  • page-templates/
    - 不同使用场景的页面样板
将资源作为起始点使用:
  • 复制组件模板创建新组件
  • 参考布局模板保持结构一致
  • 调整页面模板适配常见页面类型

本技能提供从项目搭建到部署优化的全面Astro开发指导。