본문으로 건너뛰기
cccskills
무료GitHub에 공개

web-meta-framework-astro

Astro content-first framework - islands architecture, content collections, file-based routing, SSR/SSG hybrid rendering, View Transitions, server islands, multi-framework component support

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(8)

  • SKILL.md14.9 KB
  • examples/content.md10.0 KB
  • examples/core.md6.6 KB
  • examples/integrations.md7.6 KB
  • examples/islands.md8.0 KB
  • examples/routing.md7.7 KB
  • metadata.yaml388 B
  • reference.md3.0 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Astro Patterns

Quick Guide: Astro renders pages to static HTML with zero client JavaScript by default. .astro components carry static content; framework components become interactive islands only when given a client:* directive. Content collections give structured Markdown type-safe frontmatter through Zod schemas. Rendering mode is per page: static unless export const prerender = false. Astro 6 replaced <ViewTransitions /> with <ClientRouter />, replaced Astro.glob() with import.meta.glob(), moved z from astro:content to astro/zod (now Zod 4), requires string getStaticPaths() params, and requires Node 22.12.0+.

Detailed Resources:

  • examples/core.md — typed props, expressions, nested layouts, scoped vs global styles, script handling
  • examples/islands.md — directive selection, client:only, multi-framework islands, server islands, cross-island state
  • examples/content.md — collection schemas, querying, rendering, references, custom loaders, live collections
  • examples/routing.md — static and dynamic routes, rest params, pagination, on-demand routes, endpoints, 404
  • examples/integrations.md — framework integrations, View Transitions, persistence, animations, Starlight
  • reference.md — project layout, route priority, collection API, adapters, rendering checklist

Which path applies

  • Every page is static — the default. No output setting and no adapter; dynamic routes need getStaticPaths(). Follow examples/routing.md.
  • A few pages need request-time data — keep the default, add export const prerender = false to those pages, and install a server adapter. Same file, plus the adapter table in reference.md.
  • Most pages need request-time data — set output: "server" and opt individual pages back to static with export const prerender = true.

<critical_requirements>

Before writing Astro code

Leave pages static and add export const prerender = false only where the page reads request-time data. Static is the default and is where the framework's speed comes from.

Install a server adapter before any page opts out of prerendering. Without one, a build containing prerender = false fails.

Give a framework component a client:* directive when it needs to be interactive. Without a directive it renders to static HTML and its event handlers never run.

Define collections in src/content.config.ts with a Zod schema. The schema validates frontmatter at build time and generates the types the queries return.

Use getStaticPaths() for dynamic routes in static mode. On-demand routes read Astro.params directly and need no such export.

</critical_requirements>


Auto-detection: Astro, .astro files, astro.config, islands architecture, client:load, client:visible, client:idle, client:only, client:media, server:defer, content collections, defineCollection, defineLiveCollection, getCollection, getLiveCollection, getEntry, getLiveEntry, render, astro:content, astro:transitions, ClientRouter, getStaticPaths, Astro.props, Astro.params, Astro.cookies, Astro.redirect, prerender, astro add, @astrojs/react, @astrojs/vue, @astrojs/svelte, Starlight

Applies to:

  • .astro component syntax — frontmatter, template expressions, slots, layouts, scoped styles
  • Islands: client directives, hydration timing, server islands, mixing UI frameworks on one page
  • Content collections: schemas, loaders, querying, rendering, cross-collection references
  • File-based routing: static, dynamic, rest parameters, pagination, API endpoints
  • Rendering mode: static, on-demand, and per-page prerender control
  • View Transitions: <ClientRouter />, transition directives, persisted elements

Handled elsewhere:

  • What an island renders internally — a hydrated component follows the conventions of whichever UI library wrote it, and Astro settles only the boundary.
  • Which CSS approach fills a <style> block — the scoping rules here are Astro's; the styling system is not.
  • Which store library fills the cross-island seam — that islands share no tree, and that a module-scoped store is the way across, is settled in examples/islands.md; which store you reach for is not.
  • Fully interactive applications where every route is user-specific — that shape wants a framework whose default is on-demand rendering rather than one whose default is static output.

<philosophy>

Astro is a content-first framework that ships zero JavaScript by default. Most of a page is static HTML; small interactive "islands" hydrate independently, each paying only for itself.

Four consequences follow, and they explain most of the API:

  1. A component is static until told otherwise — client:* is the opt-in, so the cost of interactivity is always visible at the call site.
  2. The UI library is a detail — React, Vue, Svelte, Solid and Preact components are all just island contents, and one page can carry several.
  3. Content is typed data — collections put a Zod schema between Markdown frontmatter and the code that reads it, so a typo in a post fails the build rather than the page.
  4. Rendering mode is per page — static and on-demand pages coexist in one project, which is why prerender is an export rather than a global setting.
</philosophy>

<decision_framework>

Static or on-demand? A page needs on-demand rendering when it reads cookies, headers or user-specific data at request time, or when its data changes faster than you are willing to rebuild. Everything else is static — including data that changes hourly, which a rebuild handles more cheaply than an adapter does.

.astro or a framework component? No client-side interactivity means .astro — zero JavaScript. Simple interactivity (a toggle, a show/hide) is .astro plus a <script> tag, which is lighter than a framework. Reach for a framework component when the interaction needs that framework's own state model.

Which client directive? The table in Pattern 4 maps each one to what it is for. client:only is the last resort, for a component that cannot server-render at all.

Build-time or live collection? defineCollection for anything that is the same on every request — posts, docs, changelogs, author bios. defineLiveCollection only when the data must be fresh per request (inventory, pricing), which also forces that page into on-demand rendering.

</decision_framework>


<patterns>

Core patterns

Pattern 1: Astro component structure

An .astro file is a server-only script between --- fences followed by an HTML template. The script never reaches the browser, so data fetching belongs there.

---
interface Props { title: string; description?: string }
const { title, description = "Default" } = Astro.props;
const posts = await getCollection("blog");
---

<h1>{title}</h1>
{posts.map((post) => <a href={`/blog/${post.id}`}>{post.data.title}</a>)}

<style>h1 { color: navy; }</style>

Styles in a <style> block are scoped to the component unless marked is:global.

Full code: examples/core.md

Pattern 2: Slots for composition

A <slot /> receives content from the parent. Named slots take a matching slot="name" attribute, and anything inside the <slot> element is fallback content when nothing is passed.

<article>
  <header><slot name="header"><h2>{title}</h2></slot></header>
  <slot />
  <footer><slot name="footer" /></footer>
</article>

Full code: examples/core.md

Pattern 3: Layouts

A layout is an ordinary component that wraps page content through its default slot, and layouts nest — a blog layout wrapping a base layout wrapping the page.

---
const { title } = Astro.props;
---
<html lang="en">
  <head><title>{title}</title></head>
  <body><main><slot /></main></body>
</html>

Full code: examples/core.md

Pattern 4: Islands and client directives

Framework components render to static HTML until a client:* directive hydrates them. The directive chooses when hydration happens.

DirectiveHydratesUse for
client:loadImmediately on page loadCritical interactive UI
client:idleWhen the browser is idleLower-priority interactivity
client:visibleWhen it scrolls into the viewportBelow-the-fold content
client:mediaWhen a media query matchesResponsive interactivity
client:onlyClient only, skipping the server renderBrowser-dependent components
<Header />                                   <!-- static, zero JS -->
<SearchBar client:load />
<Comments client:visible />
<Analytics client:media="(max-width: 768px)" />

Full code: examples/islands.md

Pattern 5: Server islands

server:defer renders a component per request while the rest of the page stays cacheable. The fallback slot holds its place until it arrives.

<ProductInfo product={product} />

<UserReviews server:defer>
  <div slot="fallback">Loading reviews...</div>
</UserReviews>

Full code: examples/islands.md

Pattern 6: Content collections

A collection pairs a loader with a Zod schema. getCollection queries it with an optional filter, and render() turns an entry's Markdown into a component.

// src/content.config.ts
const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    pubDate: z.coerce.date(),
    draft: z.boolean().default(false),
  }),
});
export const collections = { blog };
const posts = await getCollection("blog", ({ data }) => !data.draft);
const { Content, headings } = await render(post);

Live collections are a separate mechanism: defineLiveCollection in src/live.config.ts (not content.config.ts), queried with getLiveCollection() / getLiveEntry(), and only from on-demand pages.

Full code: examples/content.md

Pattern 7: File-based routing

src/pages/ maps to URLs. [param] is a single dynamic segment, [...rest] matches any depth, and a leading underscore excludes a file from routing.

src/pages/
├── index.astro          → /
├── blog/[id].astro      → /blog/:id
├── docs/[...slug].astro → /docs and /docs/*
└── _helpers.ts          → not a route

In static mode each dynamic route exports getStaticPaths() returning { params, props } pairs; paginate() inside it generates numbered pages.

Full code: examples/routing.md

Pattern 8: On-demand rendering and endpoints

export const prerender = false moves a page to request time, where Astro.cookies, Astro.redirect() and a Response return value all become available. API endpoints are .ts files exporting one handler per HTTP method, and they default to static like everything else.

export const prerender = false;

export const GET: APIRoute = async ({ url }) => {
  const query = url.searchParams.get("q");
  if (!query)
    return new Response(JSON.stringify({ error: "Missing query" }), {
      status: 400,
    });
  return new Response(JSON.stringify(await searchDatabase(query)));
};

Full code: examples/routing.md

Pattern 9: View Transitions

<ClientRouter /> in the document head enables cross-page transitions. transition:name pairs elements so they morph, and transition:persist keeps an element alive across a navigation.

<head><ClientRouter /></head>

<img src={post.data.heroImage} transition:name={`hero-${post.id}`} transition:animate="slide" />
<audio controls transition:persist><source src="/music.mp3" type="audio/mp3" /></audio>

Full code: examples/integrations.md

</patterns>

<red_flags>

Red flags

Breaks at runtime:

  • A dynamic route in static mode with no getStaticPaths() — the build fails with "getStaticPaths() is required".
  • prerender = false with no server adapter installed — the build fails.
  • <ViewTransitions /> — removed in Astro 6; import <ClientRouter /> from astro:transitions.
  • Astro.glob() — removed in Astro 6; use import.meta.glob().
  • import { z } from "astro:content" — removed in Astro 6; import z from astro/zod, which is Zod 4, so z.string().email() is now z.email().
  • Numeric getStaticPaths() params — Astro 6 requires strings; wrap with String(id).
  • astro.config.cjs — Astro 6 requires ESM (.mjs or .ts).
  • Functions, class instances or symbols passed as props to a hydrated component — island props must be serializable.
  • Astro.props read outside the frontmatter fence, or an .astro component imported into a framework component — neither is available there.
  • Astro 6 on Node below 22.12.0 — unsupported.

Surprising behaviour:

  • client:load on everything defeats the architecture; a component with no interactivity wants no directive at all.
  • client:only skips the server render, so nothing is in the HTML for crawlers — prefer client:load wherever the component can render on the server.
  • Data fetched in a <script> tag creates a client waterfall; frontmatter runs server-side and has no such cost.
  • A collection with no schema loses both build-time validation and generated types.
  • output: "server" on a mostly-static site gives up the default's caching for pages that did not need it.
  • Unfiltered getCollection returns drafts alongside published entries.
  • <style> is scoped by default — reach for <style is:global> or the :global() selector deliberately.
  • <script> is bundled and deduped; is:inline opts out, which is what makes a script re-run on every View Transitions navigation.
  • client:visible waits on IntersectionObserver, so a component that is never on screen never hydrates.
  • Astro.redirect() works only on on-demand pages; a static page cannot redirect at request time.
  • Islands share no state — cross-island communication needs a store or events you bring.
  • transition:persist needs the same transition:name on both pages, or the element is recreated.
  • Collection entry ids come from filenames unless frontmatter overrides them.
  • Live collections cannot render MDX, and import.meta.env is inlined at build time — read runtime secrets from process.env.
  • A [...slug] route matches its own base path when a params entry passes undefined.

</red_flags>

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

agents-inc의 스킬 모두 보기

이 스킬의 문제 신고