Communitygithub.com

0xDarkMatter/claude-mods

Astro-Framework-Patterns: Inselarchitektur, Content Collections, Rendering-Strategien und Deployment. Verwendung für: Astro, Inselarchitektur, Content Collections, Astro Cloudflare, View Transitions, partielle Hydratation, Astrojs, SSG, SSR, Hybrid-Rendering, Astro Adapter.

Was ist claude-mods?

Dieses Skill bietet Entwicklern eine umfassende Anleitung zur Entwicklung mit dem Astro-Framework. Es deckt die wichtigsten Konzepte ab: Inselarchitektur (Islands Architecture) für interaktive UI-Komponenten mit verschiedenen Hydratationsstrategien, Content Collections zur typsicheren Verwaltung von Inhalten, und eine Entscheidungsmatrix für die Wahl der richtigen Rendering-Strategie (SSG, SSR oder Hybrid). Darüber hinaus enthält es eine Referenz zu View Transitions für nahtlose Seitenübergänge und eine Entscheidungshilfe für das Deployment auf verschiedenen Plattformen wie Cloudflare, Vercel, Netlify oder Node.js. Das Skill richtet sich an Entwickler, die mit Astro arbeiten (auf CLI-Ebene wie Cursor, Codex oder Claude Code) und benötigt werden für Aufgaben wie die Optimierung der Build-Performance, die Implementierung dynamischer Inhalte oder die Migration von Projekten. Es unterstützt alle gängigen Astro-Plattformen und enthält praktische Codebeispiele sowie eine Liste häufiger Fehlerquellen und deren Lösungen.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/0xDarkMatter/claude-mods/tree/HEAD/skills/astro-ops

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Astro-Operationen

Faktenstand: Juli 2026.

Umfassende Muster für die Entwicklung mit dem Astro-Framework: Inselarchitektur, Content Collections, Rendering-Strategien, View Transitions und plattformübergreifendes Deployment.

Entscheidungsbaum für die Rendering-Strategie

Welche Rendering-Strategie?
│
├─ Ist der Inhalt größtenteils statisch (Blog, Doku, Marketing)?
│  ├─ JA → Ändert er sich seltener als täglich?
│  │  ├─ JA → SSG (output: 'static')
│  │  │        Schnellster TTFB, CDN-cachbar, keine Runtime-Kosten
│  │  └─ NEIN → Hybrid (output: 'hybrid')
│  │           Standardmäßig statisch + opt-in SSR pro Route
│  └─ NEIN → Benötigt jede Seite Personalisierung?
│     ├─ JA → SSR (output: 'server')
│     │        Dynamisch pro Anfrage, authentifizierungsbewusst, Echtzeitdaten
│     └─ NEIN → Hybrid (output: 'hybrid')
│              Statisches Grundgerüst + Server-Inseln für dynamische Teile
│
├─ Benötigt die App Echtzeit-Interaktivität (Dashboard, SPA)?
│  ├─ JA → Ist es eine vollständige SPA mit clientseitigem Routing?
│  │  ├─ JA → Erwäge React/Vue SPA stattdessen, oder Astro + client:only
│  │  └─ NEIN → Hybrid + Inselarchitektur
│  │           Interaktive Inseln in statischen Seiten
│  └─ NEIN → SSG (output: 'static')
│
├─ Bauzeit-Bedenken (>10.000 Seiten)?
│  ├─ JA → Hybrid mit On-Demand-Rendering
│  │        Beliebte Seiten vorgerendert, SSR für den Long Tail
│  └─ NEIN → SSG ist ausreichend
│
└─ Wird Edge Computing benötigt (niedrige Latenz weltweit)?
   ├─ JA → SSR + Cloudflare/Vercel Edge Adapter
   └─ NEIN → SSR + Node-Adapter oder SSG

Konfiguration

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

// SSG (Standard) - alle Seiten zur Bauzeit vorgerendert
export default defineConfig({
  output: 'static',
});

// SSR - alle Seiten werden bei Anfrage gerendert
export default defineConfig({
  output: 'server',
  adapter: cloudflare(), // oder vercel(), netlify(), node()
});

// Hybrid - statisch als Standard, opt-in SSR pro Seite
export default defineConfig({
  output: 'hybrid',
  adapter: cloudflare(),
});
---
// Im Hybrid-Modus: Opt-out vom Vorrendern für bestimmte Seiten:
export const prerender = false;
// Im SSR-Modus: Opt-in zum Vorrendern:
export const prerender = true;
---

Kurzreferenz Inselarchitektur

DirektiveHydratisiert wennJS ausgeliefertAnwendungsfall
client:loadSofort beim SeitenladenVolles BundleInteraktivität oberhalb der Falz (Navigation, Hero CTA)
client:idleNachdem die Seite im Leerlauf ist (requestIdleCallback)Volles BundleInteraktivität unterhalb der Falz (Kommentarformular, Chat)
client:visibleWenn in den Viewport gescrolltVolles BundleWeit unten auf der Seite (Footer-Widget, Karussell)
client:mediaWenn die Media Query zutrifftVolles BundleMobil-Navigation, responsive Komponenten
client:only="react"Sofort, SSR komplett überspringenVolles BundleKomponenten, die nicht SSR-fähig sind (Canvas, WebGL)
(keine)Niemals - nur statisches HTMLNull JSStatischer Inhalt, Karten, Kopfzeilen
---
import NavBar from '../components/NavBar.tsx';
import CommentForm from '../components/CommentForm.tsx';
import ImageCarousel from '../components/ImageCarousel.svelte';
import MobileMenu from '../components/MobileMenu.vue';
import ThreeScene from '../components/ThreeScene.tsx';
---

<!-- Wird sofort geladen - kritische Interaktivität -->
<NavBar client:load />

<!-- Wird geladen, nachdem die Seite im Leerlauf ist - nicht kritisch -->
<CommentForm client:idle />

<!-- Wird geladen, wenn in den Viewport gescrollt - Lazy Loading -->
<ImageCarousel client:visible />

<!-- Wird nur auf Mobilgeräten geladen -->
<MobileMenu client:media="(max-width: 768px)" />

<!-- Nur Client-seitig, kein SSR (WebGL kann nicht auf dem Server laufen) -->
<ThreeScene client:only="react" />

Content Collections Schnellstart

Schema definieren

// src/content.config.ts (Astro 5) oder src/content/config.ts (Astro 4)
import { defineCollection, z, reference } from 'astro:content';
import { glob } from 'astro/loaders';

const blog = defineCollection({
  loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
  schema: z.object({
    title: z.string(),
    description: z.string().max(160),
    pubDate: z.coerce.date(),
    updatedDate: z.coerce.date().optional(),
    heroImage: z.string().optional(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
    author: reference('authors'), // Referenz auf eine andere Sammlung
  }),
});

const authors = defineCollection({
  loader: glob({ pattern: '**/*.json', base: './src/content/authors' }),
  schema: z.object({
    name: z.string(),
    avatar: z.string(),
    bio: z.string(),
    socials: z.object({
      twitter: z.string().optional(),
      github: z.string().optional(),
    }).optional(),
  }),
});

export const collections = { blog, authors };

Sammlungen abfragen

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

// Alle nicht als Entwurf markierten Blogbeiträge, sortiert nach Datum
const posts = (await getCollection('blog', ({ data }) => !data.draft))
  .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

// Einzelnen Eintrag abrufen
const post = await getEntry('blog', 'my-first-post');

// Eine Referenz auflösen
const author = await getEntry(post.data.author);

// Inhalt rendern
const { Content, headings } = await post.render();
---

<Content />

Content Collections vs. Externes CMS

KriteriumContent CollectionsExternes CMS (Payload, etc.)
InhaltstypLokales Markdown/MDX, Doks, BlogsRelationale Datenmodelle
AutorenEntwickler (versionskontrolliert)Redakteure (Admin-UI, Multi-User-Auth)
ValidierungTypsicher via Zod zur BauzeitCMS-seitige Schemas + API-Verträge
AktualisierungsrhythmusWird mit der Website deployedUnabhängig von Deployments
API-BedarfKeiner (Bauzeit-Abfragen)REST/GraphQL für andere Konsumenten
WorkflowGit-PRs, einfache ÜberprüfungRedaktionelle Workflows, Entwürfe, Rollen

Faustregel: Mit Content Collections beginnen; erst dann zu einem CMS greifen, wenn Nicht-Entwickler ohne Deployment veröffentlichen müssen oder der Inhalt wirklich relational ist.

Referenz zur Projektstruktur

project-root/
├── astro.config.mjs          # Astro-Konfiguration
├── tsconfig.json              # TypeScript-Konfiguration (erweitert astro/tsconfigs)
├── package.json
├── public/                    # Statische Assets (werden unverändert kopiert)
│   ├── favicon.svg
│   ├── robots.txt
│   └── og-image.png
├── src/
│   ├── pages/                 # Dateibasiertes Routing
│   │   ├── index.astro        # → /
│   │   ├── about.astro        # → /about
│   │   ├── blog/
│   │   │   ├── index.astro    # → /blog
│   │   │   └── [slug].astro   # → /blog/:slug (dynamisch)
│   │   ├── api/
│   │   │   └── search.ts      # → /api/search (API-Endpunkt)
│   │   └── [...slug].astro    # → Catch-all/404
│   ├── layouts/
│   │   ├── BaseLayout.astro   # HTML-Gerüst, <head>, globale Styles
│   │   └── BlogPost.astro     # Blogbeitrag-Layout
│   ├── components/
│   │   ├── Header.astro       # Statische Astro-Komponente
│   │   ├── Footer.astro
│   │   ├── NavBar.tsx         # React-Insel
│   │   └── Counter.svelte     # Svelte-Insel
│   ├── content/               # Quellendateien der Content Collections
│   │   ├── blog/
│   │   │   ├── post-one.md
│   │   │   └── post-two.mdx
│   │   └── authors/
│   │       └── jane.json
│   ├── content.config.ts      # Sammlungsschemas (Astro 5)
│   ├── middleware.ts           # Request/Response-Middleware
│   ├── styles/
│   │   └── global.css
│   └── lib/                   # Gemeinsame Hilfsprogramme
│       ├── utils.ts
│       └── constants.ts
└── .env                       # Umgebungsvariablen

Kurzreferenz View Transitions

---
// src/layouts/BaseLayout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html>
  <head>
    <ViewTransitions />
  </head>
  <body>
    <slot />
  </body>
</html>

Übergangsdirektiven

<!-- Element seitenübergreifend beibehalten (behält Zustand, vermeidet Neu-Rendering) -->
<audio transition:persist id="player">
  <source src="/music.mp3" />
</audio>

<!-- Benannte Transition für Animationspaarung -->
<img transition:name="hero" src={post.heroImage} />

<!-- Benutzerdefinierte Animation -->
<div transition:animate="slide">Inhalt</div>
<div transition:animate="fade">Inhalt</div>
<div transition:animate="none">Keine Animation</div>

<!-- Mit Name beibehalten (für mehrere persistente Elemente) -->
<video transition:persist="media-player" />

Lifecycle-Ereignisse

<script>
  document.addEventListener('astro:before-preparation', (e) => {
    // Bevor die neue Seite abgerufen wird - Navigation abbrechen, Ladeanimation anzeigen
  });

  document.addEventListener('astro:after-preparation', (e) => {
    // Neue Seite abgerufen, vor dem Austausch
  });

  document.addEventListener('astro:before-swap', (e) => {
    // DOM-Austauschverhalten anpassen
  });

  document.addEventListener('astro:after-swap', () => {
    // DOM aktualisiert - Skripte neu initialisieren
  });

  document.addEventListener('astro:page-load', () => {
    // Seite vollständig geladen (wird bei der ersten und jeder Navigation ausgelöst)
    // Dies anstelle von DOMContentLoaded mit View Transitions verwenden
  });
</script>

Zurück/Vorwärts-Handhabung

// astro.config.mjs
export default defineConfig({
  prefetch: {
    prefetchAll: true,         // Alle Links beim Hover vorabrufen
    defaultStrategy: 'hover',  // 'hover' | 'tap' | 'viewport' | 'load'
  },
});
<!-- Vorabrufsteuerung pro Link -->
<a href="/about" data-astro-prefetch>Vorabruf bei Hover (Standard)</a>
<a href="/blog" data-astro-prefetch="viewport">Vorabruf, wenn sichtbar</a>
<a href="/contact" data-astro-prefetch="load">Sofortiger Vorabruf</a>
<a href="/external" data-astro-prefetch="false">Kein Vorabruf</a>

Entscheidungsbaum für das Deployment

Wo deployen?
│
├─ Wird Edge Computing + Cloudflare-Ökosystem benötigt (KV, D1, R2)?
│  └─ Cloudflare Pages/Workers
│     Adapter: @astrojs/cloudflare
│     Am besten für: Globales Edge, Workers-Bindings, kosteneffizient
│
├─ Wird Serverless + Vercel-Ökosystem benötigt (ISR, Analytics)?
│  └─ Vercel
│     Adapter: @astrojs/vercel
│     Am besten für: Next.js-Migration, Bildoptimierung, ISR
│
├─ Wird Serverless + Netlify-Ökosystem benötigt (Formulare, Identity)?
│  └─ Netlify
│     Adapter: @astrojs/netlify
│     Am besten für: JAMstack, eingebaute Formulare, Split-Testing
│
├─ Wird vollständige Serverkontrolle benötigt (Docker, benutzerdefinierte Runtime)?
│  └─ Node.js (eigenständig oder Express/Fastify)
│     Adapter: @astrojs/node
│     Am besten für: Selbst gehostet, WebSocket, langlebige Prozesse
│
└─ Reine statische Seite (kein SSR erforderlich)?
   └─ Jeder statische Host (GitHub Pages, S3, Cloudflare Pages)
      Kein Adapter erforderlich, output: 'static'
      Am besten für: Blogs, Doks, Marketing-Websites

Adapter-Installation

# Cloudflare
npx astro add cloudflare

# Vercel
npx astro add vercel

# Netlify
npx astro add netlify

# Node.js
npx astro add node

Häufige Fehlerquellen

FehlerWarumLösung
Hydrationsfehler durch NichtübereinstimmungServer-HTML unterscheidet sich vom Client-Render (Daten, zufällige IDs, Browser-APIs)client:only für browserabhängige Komponenten verwenden oder deterministisches Rendering sicherstellen
import.meta.env im Client undefiniertNur PUBLIC_-Präfix-Variablen sind für clientseitigen Code verfügbarIn PUBLIC_MY_VAR umbenennen oder über Props vom Server übergeben
Dynamische Routen 404 bei SSGgetStaticPaths() gibt nicht alle möglichen Parameter zurückSicherstellen, dass getStaticPaths() jeden gültigen Pfad zurückgibt, oder auf Hybrid/SSR umstellen
Bilder werden nicht optimiertVerwendung von <img> anstelle der Astro-Komponente <Image />Aus astro:assets importieren: import { Image } from 'astro:assets' und lokale Imports für src verwenden
SSR schlägt ohne Adapter fehloutput: 'server' oder 'hybrid' erfordert einen Deployment-AdapterAdapter installieren: npx astro add cloudflare (oder vercel, netlify, node)
MDX-Komponenten werden nicht gerendertBenutzerdefinierte Komponenten nicht an MDX-Inhalt übergebenKomponenten über <Content components={{ MyComponent }} /> übergeben oder MDX-Konfiguration in astro.config.mjs verwenden
Schemaänderungen in Content Collections werden nicht übernommenTypgenerierung ist zwischengespeichert, veraltete .astro-Typenastro sync ausführen, um Typen neu zu generieren, Dev-Server neu starten
client:* auf Astro-KomponentenClient-Direktiven funktionieren nur auf Framework-Komponenten (React, Vue, Svelte)Astro-Komponenten sind rein statisch; interaktive Teile in eine Framework-Komponente auslagern
document / window ist nicht definiertServerseitiger Code kann nicht auf Browser-Globals zugreifenMit if (typeof window !== 'undefined') absichern oder in client:only verschieben
Styles leaken zwischen KomponentenVerwendung von globalem CSS anstelle von bereichsbezogenen Styles<style> (standardmäßig bereichsbezogen in .astro) oder <style is:global> gezielt verwenden
View Transitions unterbrechen SkripteDOMContentLoaded feuert mit View Transitions nur einmalastro:page-load-Ereignis verwenden, das bei jeder Navigation feuert
Umgebungsvariablen fehlen in Produktion.env nicht geladen oder Plattform-Env-Vars nicht konfiguriertenvField in astro.config.mjs zur Validierung verwenden; Variablen im Platform-Dashboard setzen

Sicherheitscheckliste für die Produktion

Für jedes Produktions-Deployment Folgendes beachten:

  • CSP-Header - eine restriktive Content-Security-Policy konfigurieren (siehe Middleware-Muster in references/deployment.md)
  • Remote-Bildbeschränkungen - explizite image.domains / remotePatterns-Whitelists erzwingen; Bild-URLs niemals aus Benutzereingaben ableiten (SSRF-Risiko)
  • Host-Header-Validierung - überprüfen, ob der Request-Host mit den erwarteten Domains übereinstimmt (nur SSR/Hybrid)
  • Geheimnisverwaltung - bei Cloudflare Workers Bindings verwenden (wrangler secret put), keine in den Code eingebackenen Env-Vars; andernfalls Plattform-Geheimnisspeicher verwenden
  • Nur HTTPS - sicherstellen, dass alle externen Ressourcen (Skripte, Bilder, Schriftarten) über HTTPS geladen werden
  • Eingabevalidierung - alle Benutzereingaben in SSR-Kontexten bereinigen (Query-Parameter, Formulardaten, Cookies)

Referenzdateien

DateiInhaltZeilen
references/content-collections.mdSchema-Muster, Zod-Typen, Abfragen, MDX, Content-Layer-API, Migrationen~500
references/islands-rendering.mdErweiterte Hydrations-Muster, Server-Inseln, Leistungsoptimierung, Framework-Besonderheiten~400
references/view-transitions.mdErweiterte Übergangsanimationen, Lifecycle-Hooks, benutzerdefinierte Verhaltensweisen zur Barrierefreiheit~300
references/deployment.mdKonfigurationen für einzelne Adapter, CSP-Middleware, Build-Optimierung, Env-Validierung~600
references/seo.mdMetadaten, strukturierte Daten, Open Graph, Sitemaps, RSS-Feeds~350

Zugehörige Skills

  • astro-seo - SEO, strukturierte Daten, Sitemaps, RSS/Atom-Feeds (lokalisiert in references/seo.md)
  • web-performance - Metriken (Web Vitals, LCP, TBT), Caching-Strategien, Lazy Loading, Asset-Optimierung
  • responsive-tailwind - Responsive Design, Utility-First-CSS, mobile Navigation, Medienabfragen, Adaptive Layouts
  • cloudflare-deployment - Cloudflare Workers-Seiten, KV, D1, R2, Bindings, CI/CD

Skill ID: 0xDarkMatter/claude-mods

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Verwandte Skills