astro
π―Skillfrom joabgonzalez/ai-agents-framework
Builds optimized, performant static and server-rendered websites using Astro, TypeScript, and minimal JavaScript with optional React component islands.
Part of
joabgonzalez/ai-agents-framework(11 items)
Installation
npm run devSkill Details
"Building fast, optimized websites using Astro with TypeScript and optional React islands. SSG, SSR, partial hydration, component islands. Trigger: When building Astro websites, implementing component islands, or configuring SSG/SSR."
Overview
# Astro Skill
Overview
This skill provides guidance for building static sites with Astro, focusing on SSG patterns, minimal JavaScript, proper directive usage, and integration with React islands.
Objective
Enable developers to build fast, optimized static sites using Astro with proper TypeScript support, minimal runtime JavaScript, and effective use of client directives for interactivity.
---
When to Use
Use this skill when:
- Building static websites with SSG (Static Site Generation)
- Creating server-rendered sites with SSR (Server-Side Rendering)
- Implementing hybrid SSG + SSR approaches
- Creating content-focused sites (blogs, documentation, marketing)
- Implementing partial hydration with component islands
- Using React/Vue/Svelte components selectively
- Optimizing for performance and minimal JavaScript
- Building with dynamic data that needs server rendering
Don't use this skill for:
- Full SPA applications (use react or vue directly)
- Highly dynamic, client-heavy apps requiring constant client state
- Real-time dashboards with WebSocket connections
---
π Extended Mandatory Read Protocol
This skill has a references/ directory with detailed guides for rendering strategies, content, and interactivity.
Reading Rules
Read references/ when:
- MUST read [ssg-patterns.md](references/ssg-patterns.md) when:
- Building static sites (no adapter)
- Using getStaticPaths for dynamic routes
- Fetching data at build time
- MUST read [ssr-patterns.md](references/ssr-patterns.md) when:
- Building dynamic pages with user-specific data
- Using Astro.locals, server endpoints
- Implementing authentication
- MUST read [hybrid-strategies.md](references/hybrid-strategies.md) when:
- Combining SSG + SSR in same project
- Migrating from SSG to Hybrid
- Deciding which pages should be static vs dynamic
- MUST read [client-directives.md](references/client-directives.md) when:
- Adding interactivity to static pages
- Choosing load/visible/idle/only strategies
- Optimizing JavaScript bundle size
- CHECK [content-collections.md](references/content-collections.md) when:
- Managing blog posts, documentation
- Type-safe content with schemas
- CHECK [actions.md](references/actions.md) when:
- Handling form submissions
- Server-side validation
Quick reference only: Use this SKILL.md for project type detection and quick decisions. Decision Tree below directs you to specific references.
Reading Priority
| Situation | Read This | Why |
| ------------------------ | ----------------------------------- | ------------------------------ |
| Static site (no adapter) | ssg-patterns.md (REQUIRED) | 50+ SSG-specific patterns |
| Dynamic site (adapter) | ssr-patterns.md (REQUIRED) | Authentication, server context |
| Mixing SSG + SSR | hybrid-strategies.md (REQUIRED) | Decision matrix, migration |
| Adding interactivity | client-directives.md (REQUIRED) | 6 hydration strategies |
| Content management | content-collections.md (CHECK) | Type-safe schemas |
| Form handling | actions.md (CHECK) | Server validation |
See [references/README.md](references/README.md) for complete navigation guide.
---
Critical Patterns
β REQUIRED: Detect Project Type First
```javascript
// Check astro.config.mjs to understand project type:
// β SSG-only project (no adapter)
export default defineConfig({
output: 'static', // or omit (default)
// No adapter = SSG-only project
});
// β SSR project (has adapter)
export default defineConfig({
output: 'server',
adapter: node(), // Adapter present = SSR capable
});
// β Hybrid project (has adapter + hybrid mode)
export default defineConfig({
output: 'hybrid',
adapter: node(), // Can do both SSG and SSR
});
// β WRONG: Using SSR patterns in SSG-only project
// If no adapter in config, DON'T use:
// - export const prerender = false
// - Astro.locals
// - Server endpoints with POST/PUT/DELETE
```
β REQUIRED: Use .astro Components by Default
```astro
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
{title}
```
β REQUIRED: Use Client Directives Sparingly
```astro
```
β REQUIRED: Use getStaticPaths for Dynamic Routes (SSG)
```typescript
// β CORRECT: Pre-render all routes at build time (SSG)
export async function getStaticPaths() {
const posts = await getPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
```
β CHOOSE: SSG vs SSR Based on Project Type and Data Freshness
```typescript
// β SSG-only project (output: 'static', no adapter)
// ONLY use these patterns:
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
const posts = await getPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
// All data fetched at build time
// β WRONG in SSG-only: Using SSR-only features
// export const prerender = false; // ERROR: No adapter installed
// const user = Astro.locals.user; // ERROR: Only works in SSR
// β SSR project (output: 'server', has adapter)
// src/pages/dashboard.astro
export const prerender = false; // Valid: adapter installed
const user = Astro.locals.user; // Access server context
const data = await fetchUserData(user.id); // Fetch on each request
// β Hybrid project (output: 'hybrid', has adapter)
// Default pages are SSG (fast), opt-in to SSR when needed
// src/pages/index.astro β SSG (no prerender declaration)
// src/pages/profile.astro β SSR (export const prerender = false)
// β WRONG: SSR for static content (wastes server resources)
export const prerender = false; // Don't do this for blogs/static pages
```
β REQUIRED: Configure Output Mode Correctly
```javascript
// astro.config.mjs
// β SSG (default): Static site, all pages pre-rendered
export default defineConfig({
output: 'static', // or omit (default)
});
// β SSR: Server-side rendering for all pages
export default defineConfig({
output: 'server',
adapter: node(), // Requires adapter: node, vercel, netlify, etc.
});
// β HYBRID: SSG by default, opt-in to SSR per page
export default defineConfig({
output: 'hybrid',
adapter: node(),
});
```
---
Conventions
Refer to conventions for:
- Code organization
- Naming patterns
Refer to a11y for:
- Semantic HTML
- Keyboard navigation
- ARIA usage
Astro Specific
- Prefer static rendering over client-side JavaScript
- Use client directives appropriately (client:load, client:visible, client:idle)
- Keep components in
.astroformat when possible - Use React/Vue/Svelte only when client interactivity is needed
- Leverage Astro's built-in optimizations (image optimization, CSS bundling)
---
Decision Tree
First: CHECK astro.config.mjs β Identify project type. MUST read corresponding reference file.
No adapter (SSG-only)? β MUST read [ssg-patterns.md](references/ssg-patterns.md) for getStaticPaths, build-time data fetching, pagination.
Has adapter + output: 'server'? β MUST read [ssr-patterns.md](references/ssr-patterns.md) for Astro.locals, server endpoints, authentication.
Has adapter + output: 'hybrid'? β MUST read [hybrid-strategies.md](references/hybrid-strategies.md) for SSG vs SSR decision matrix, then check both ssg-patterns.md and ssr-patterns.md as needed.
Adding interactivity? β MUST read [client-directives.md](references/client-directives.md) to choose: client:load (immediate), client:visible (lazy), client:idle (low priority), client:only (CSR), or no directive (static).
Managing content (blog, docs)? β CHECK [content-collections.md](references/content-collections.md) for type-safe schemas and querying.
Building forms? β CHECK [actions.md](references/actions.md) for server-side validation and progressive enhancement.
Need smooth page transitions? β CHECK [view-transitions.md](references/view-transitions.md) for animations, lifecycle events, and accessibility.
Need authentication or request logging? β CHECK [middleware.md](references/middleware.md) for auth, redirects, and request interception.
Need to manage API keys or secrets? β CHECK [env-variables.md](references/env-variables.md) for .env files, PUBLIC\_ prefix, and security.
Want faster navigation? β CHECK [prefetch.md](references/prefetch.md) for hover, tap, viewport, and load strategies.
Static content that rarely changes? β Use SSG. See [ssg-patterns.md](references/ssg-patterns.md).
Content needs fresh data on every request? β Use SSR with prerender: false. See [ssr-patterns.md](references/ssr-patterns.md).
Dynamic routes with pre-known paths? β Use getStaticPaths (SSG). See [ssg-patterns.md#getstaticpaths-for-dynamic-routes](references/ssg-patterns.md#getstaticpaths-for-dynamic-routes).
Dynamic routes with user-specific data? β Use SSR with prerender: false. See [ssr-patterns.md#database-queries](references/ssr-patterns.md#database-queries).
Immediately visible interaction? β Use client:load. See [client-directives.md#clientload-immediate](references/client-directives.md#clientload-immediate).
Below fold interaction? β Use client:visible. See [client-directives.md#clientvisible-lazy-load](references/client-directives.md#clientvisible-lazy-load).
Non-critical interaction? β Use client:idle. See [client-directives.md#clientidle-low-priority](references/client-directives.md#clientidle-low-priority).
---
Example
SSG (Static Site Generation)
```astro
---
// src/pages/blog/[slug].astro
interface Props {
post: { title: string; content: string };
}
// Pre-render all blog posts at build time
export async function getStaticPaths() {
const posts = await getPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
---
{post.title}
```
SSR (Server-Side Rendering)
```astro
---
// src/pages/dashboard.astro
export const prerender = false; // Enable SSR for this page
// Access server context (user session, cookies, etc.)
const user = Astro.locals.user;
// Fetch fresh data on each request
const data = await fetchUserData(user.id);
---
Last login: {data.lastLogin}Welcome, {user.name}
```
Hybrid (SSG + SSR)
```javascript
// astro.config.mjs
import { defineConfig } from "astro/config";
import node from "@astrojs/node";
export default defineConfig({
output: "hybrid", // SSG by default, opt-in SSR per page
adapter: node({ mode: "standalone" }),
});
```
```astro
---
// src/pages/index.astro (SSG, pre-rendered)
const posts = await getPosts(); // Fetched at build time
---
Latest Posts
{posts.map(p =>
---
// src/pages/profile.astro (SSR, rendered on request)
export const prerender = false;
const user = Astro.locals.user; // Server-only data
---
{user.name}'s Profile
```
Edge Cases
Detect project type: Check astro.config.mjs for output mode and adapter presence before suggesting SSR solutions.
SSG-only project errors: If no adapter, avoid prerender: false, Astro.locals, Astro.request.method === 'POST'. These cause build errors.
SSR requires adapter: Install adapter (node, vercel, netlify) when using output: 'server' or output: 'hybrid'. Cannot use SSR features without adapter.
getStaticPaths in SSR: Not needed when prerender: false (SSR mode) since routes render on request. Only use in SSG pages.
Hybrid default behavior: Pages without prerender declaration default to SSG. Explicitly set prerender: false only for SSR pages.
Environment variables: Use PUBLIC_ prefix for client-side vars, no prefix for server-only (SSR) vars. SSG-only projects only use build-time vars.
Client directives work everywhere: client:load, client:visible, etc. work in both SSG and SSR projects. Only hydration strategy.
Build vs runtime errors: SSG errors appear at build time, SSR errors appear at request time. Test SSR pages locally with npm run dev.
Migration SSG β SSR: Install adapter, change output to 'hybrid' or 'server', add prerender: false to specific pages only.
---
Advanced Architecture Patterns
β οΈ Conditional Application: Architecture patterns (Clean Architecture, DDD, SOLID) apply to Astro projects only when:
- AGENTS.md explicitly specifies architecture requirements
- Codebase already uses domain/, application/, infrastructure/ folders
- User explicitly requests architectural patterns
- Complex server-side business logic exists (beyond static content rendering)
Most Astro projects (marketing sites, blogs, documentation) β Skip architecture patterns, use Astro best practices.
When Astro Needs Architecture
SSR/API projects with:
- Complex authentication/authorization
- Heavy business logic on server (not just content rendering)
- Multiple API integrations
- Domain-driven features (e-commerce, SaaS dashboards)
SSG projects typically don't need architecture patterns (content-focused, minimal logic).
Applicable Patterns
- SRP: Separate services, repositories, validation from .astro pages
- Result Pattern: Type-safe error handling in server-side operations
- Layer Separation: domain/, infrastructure/, pages/ when business logic is complex
For Complete Guide
MUST read [architecture-patterns/references/frontend-integration.md](../architecture-patterns/references/frontend-integration.md) for:
- Layer separation in Astro SSR
- Service layer patterns
- Result Pattern in .astro pages
- When to apply and when to skip
- Complete Astro examples with architecture
Also see: [architecture-patterns/SKILL.md](../architecture-patterns/SKILL.md) for pattern selection.
body: JSON.stringify({ email, name })
});
const data = await response.json();
return Result.ok(new User(data.id, data.email, data.name));
} catch (error) {
return Result.fail('Failed to create user');
}
}
};
// pages/register.astro (Presentation layer)
import { userService } from '../infrastructure/services/userService';
let result = null;
if (Astro.request.method === 'POST') {
const formData = await Astro.request.formData();
const email = formData.get('email') as string;
const name = formData.get('name') as string;
result = await userService.createUser(email, name);
}
---
{result && !result.isSuccess && (
{result.error}
)}
{result?.isSuccess && (
User registered: {result.value.name}
)}
```
#### Result Pattern in Astro
```typescript
// Result pattern for API calls
export class Result
private constructor(
public readonly isSuccess: boolean,
public readonly value?: T,
public readonly error?: string
) {}
static ok
return new Result(true, value);
}
static fail
return new Result(false, undefined, error);
}
}
// Usage in Astro page
---
const result = await dataService.getData();
---
{result.isSuccess ? (
{result.value.map(item =>
) : (
Error: {result.error}
)}
```
When to Apply
- SSR project with adapter (node, vercel, netlify)
- Complex server logic (auth, business rules, data processing)
- Project specifies architecture in
AGENTS.md - Multiple developers need structure
When NOT to Apply
- SSG-only projects (static blogs, docs, marketing sites)
- Content-focused sites with minimal logic
- Prototypes or MVPs
- Small projects (<20 pages)
For Complete Guide
MUST read [architecture-patterns/references/frontend-integration.md](../architecture-patterns/references/frontend-integration.md) for:
- Astro-specific layer separation
- Service layer patterns for SSR
- Result Pattern in
.astropages - Complete examples with domain logic
Also see: [architecture-patterns/SKILL.md](../architecture-patterns/SKILL.md) for Decision Tree and pattern applicability.
---
References
- https://docs.astro.build/
- https://docs.astro.build/en/guides/client-side-scripts/
More from this repository10
Configures advanced, accessible data tables in React using AG Grid with TypeScript-driven type safety and performance optimizations.
Generates, refactors, and debugs JavaScript code with best practices, offering intelligent suggestions for performance and clean architecture.
Provides advanced TypeScript code generation, type inference, refactoring, and best practice recommendations for robust software development
Provides expert guidance on software design patterns, architectural styles, and best practices for scalable and maintainable system architectures.
Configures and enforces code quality standards using ESLint for JavaScript and TypeScript projects, with automatic linting and error correction.
Generates React component structures, implements hooks, manages state, and provides best practices for scalable and performant web applications.
Validates and standardizes code structure, naming conventions, and best practices across programming languages and frameworks.
Rapidly style web interfaces using utility-first CSS classes with Tailwind's responsive and customizable design system.
Guides users through creating standards-compliant agent definitions by enforcing context gathering, using markdown templates, and ensuring clarity and proper metadata.
Automates web accessibility testing, generating WCAG compliance reports and recommending fixes for inclusive digital experiences.