SSkilltecabyclaudinhocode
Enviar skill
← Voltar para o catálogo

astro-docs

Escrita e Conteúdo

Scaffold and develop Astro projects with correct v5 patterns. Use when: (1) creating new Astro projects (blogs, docs/Starlight, ecommerce, portfolios, landing pages), (2) scaffolding individual Astro components, pages, layouts, or islands, (3) setting up content collections with the Content Layer API, (4) configuring integrations, routing, or deployment, (5) working with .astro files or astro.conf

1estrelas
Ver no GitHub ↗Autor: asachs01

Astro Project Scaffolding & Development

Context / Trigger Conditions

  • User asks to create a new Astro project or site
  • User asks to scaffold components, pages, layouts, or islands
  • User asks about Astro-specific patterns (content collections, view transitions, islands, etc.)
  • Working directory contains .astro files, astro.config.*, or src/pages/
  • User mentions "Astro", "Starlight", or "astro components"

Prerequisites

  • Node.js: v18.20.8+, v20.3.0+, or v22.0.0+ (v19/v21 not supported)
  • Package manager: npm, pnpm, or yarn

Quick Project Creation

# Standard project
npm create astro@latest

# With template
npm create astro@latest -- --template <template-name>

# Starlight docs site
npm create astro@latest -- --template starlight

# With integrations
npm create astro@latest -- --add react --add tailwind

Project Structure (Astro v5)

project-root/
  public/              # Static assets (copied as-is to build output)
    robots.txt
    favicon.svg
  src/
    components/        # Reusable .astro or framework components
    content/           # (optional) Content collection data
    images/            # Images processed by Astro's image optimization
    layouts/           # Page layout components
    pages/             # File-based routing (each file = a route)
      index.astro
      about.astro
      blog/
        [slug].astro   # Dynamic route
    styles/            # Global CSS/Sass
    content.config.ts  # Content collection definitions
  astro.config.mjs     # Astro configuration
  tsconfig.json        # TypeScript config (extends astro/tsconfigs/base)
  package.json

Astro Component Anatomy

---
// Component Script (server-side only, never sent to browser)
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';

// Props with TypeScript
interface Props {
  title: string;
  description?: string;
}

const { title, description = "Default description" } = Astro.props;

// Fetch data, access environment variables, etc.
const data = await fetch('https://api.example.com/data').then(r => r.json());
---

<!-- Component Template (HTML + JS Expressions) -->
<Layout title={title}>
  <h1>{title}</h1>
  <p>{description}</p>

  {/* Conditional rendering */}
  {data && <Card title={data.name} />}

  {/* List rendering */}
  <ul>
    {data.items.map(item => <li>{item.name}</li>)}
  </ul>

  {/* Named slot */}
  <slot name="sidebar" />

  {/* Default slot */}
  <slot />
</Layout>

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

<script>
  // Client-side JavaScript (bundled, deduped)
  console.log('This runs in the browser');
</script>

Content Collections (Content Layer API - Astro v5)

Configuration: src/content.config.ts

import { defineCollection, reference } from 'astro:content';
import { glob, file } 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(),
    description: z.string(),
    pubDate: z.coerce.date(),
    updatedDate: z.coerce.date().optional(),
    heroImage: z.string().optional(),
    draft: z.boolean().default(false),
    author: reference('authors'),        // Reference another collection
    tags: z.array(z.string()).default([]),
  })
});

const authors = defineCollection({
  loader: glob({ pattern: "**/*.json", base: "./src/content/authors" }),
  schema: z.object({
    name: z.string(),
    email: z.string().email(),
    avatar: z.string().url().optional(),
  })
});

// Remote data collection (inline loader)
const products = defineCollection({
  loader: async () => {
    const response = await fetch("https://api.example.com/products");
    const data = await response.json();
    return data.map((item: any) => ({ id: item.sku, ...item }));
  },
  schema: z.object({
    name: z.string(),
    price: z.number(),
    inStock: z.boolean(),
  })
});

export const collections = { blog, authors, products };

Querying Collections

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

// Get all entries
const posts = (await getCollection('blog'))
  .filter(post => !post.data.draft)
  .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

// Get single entry
const featured = await getEntry('blog', 'my-first-post');

// Render markdown content
const { Content, headings } = await render(featured);
---

Dynamic Routes from Collections

---
// src/pages/blog/[...slug].astro
import { getCollection, render } from 'astro:content';

export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map(post => ({
    params: { slug: post.id },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content } = await render(post);
---

<article>
  <h1>{post.data.title}</h1>
  <time>{post.data.pubDate.toLocaleDateString()}</time>
  <Content />
</article>

Layouts

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

const { title, description } = Astro.props;
---

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content={description} />
    <title>{title}</title>
    <slot name="head" />
  </head>
  <body>
    <header>
      <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
        <a href="/blog">Blog</a>
      </nav>
    </header>
    <main>
      <slot />
    </main>
    <footer>
      <slot name="footer">
        <p>&copy; {new Date().getFullYear()}</p>
      </slot>
    </footer>
  </body>
</html>

Islands Architecture (Client Directives)

---
import ReactCounter from '../components/Counter.jsx';
import VueWidget from '../components/Widget.vue';
import SvelteToggle from '../components/Toggle.svelte';
---

<!-- No JS sent to client (static HTML only) -->
<ReactCounter />

<!-- Hydrate on page load -->
<ReactCounter client:load />

<!-- Hydrate when visible in viewport -->
<VueWidget client:visible />

<!-- Hydrate when idle -->
<SvelteToggle client:idle />

<!-- Hydrate on specific media query -->
<ReactCounter client:media="(max-width: 768px)" />

<!-- Only render on client (skip SSR) -->
<ReactCounter client:only="react" />

Server Islands (Astro v5)

---
import UserGreeting from '../components/UserGreeting.astro';
---

<!-- Defer rendering, show fallback while loading -->
<UserGreeting server:defer>
  <div slot="fallback">Loading user data...</div>
</UserGreeting>

Astro Configuration (astro.config.mjs)

import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwind from '@astrojs/tailwind';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
import vercel from '@astrojs/vercel';

export default defineConfig({
  site: 'https://example.com',
  base: '/docs',               // If deployed to subpath
  trailingSlash: 'always',

  integrations: [
    react(),
    tailwind(),
    mdx(),
    sitemap(),
  ],

  // SSR adapter (for on-demand rendering)
  adapter: vercel(),
  output: 'server',            // 'static' (default) | 'server' | 'hybrid'

  // Vite config passthrough
  vite: {
    css: { preprocessorOptions: { scss: { api: 'modern-compiler' } } },
  },

  // Image optimization
  image: {
    domains: ['cdn.example.com'],
  },

  // i18n routing
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr'],
    routing: { prefixDefaultLocale: false },
  },
});

Starlight Documentation Site

Setup

npm create astro@latest -- --template starlight

Configuration

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

export default defineConfig({
  integ

Como adicionar

/plugin marketplace add asachs01/astro-docs-skill

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Comentários · Nenhum comentário

Entre para comentar. Entrar

  • Ainda não há comentários. Seja o primeiro.