Communitygithub.com

ajelinek/skills-stash

Nutze dieses Skill beim Schreiben oder Refaktorieren von Astro TypeScript-Code: Astro für statische Seiten und Layouts, SolidJS oder React Islands für alle Interaktivität, CSS Modules in separaten Dateien, Hydrationsdirektiven, Content Collections, Server Islands, On-Demand-Rendering, Astro Actions und zugängliches semantisches HTML. Verwende es zusammen mit `ui-engineering`, wenn die Aufgabe auch gemeinsame UI-Struktur, Styling, Semantik, Barrierefreiheit oder Entscheidungen zu Basis-Komponenten betrifft.

Was ist skills-stash?

Dieses Skill definiert die Architekturprinzipien und Codierungsstandards für Astro TypeScript-Projekte. Es etabliert eine klare Trennung zwischen statischem HTML-Rendering (Astro) und interaktiven Komponenten (SolidJS oder React Islands) und verhindert so fragile und untestbare Muster. Das Skill erzwingt die Verwendung von CSS Modules in separaten Dateien für das gesamte Styling, beschreibt die Projektstruktur mit klaren Namenskonventionen und behandelt fortgeschrittene Themen wie Content Collections, Server Islands, SSR und Astro Actions. Es ist für Entwickler gedacht, die konsistente, wartbare und zugängliche Astro-Anwendungen erstellen, und enthält Verweise auf detaillierte Referenzdateien für tiefere Einblicke. Unterstützte Plattformen: Claude Code, Cursor, Codex und andere KI-Tools mit Skill-Unterstützung.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ajelinek/skills-stash/tree/HEAD/astro.js

In Ihrer bevorzugten KI fragen

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

Dokumentation

Astro

Astro besitzt die statische Struktur: Seiten, Layouts und rein präsentative Bereiche. SolidJS oder React besitzt die gesamte Interaktivität: Jede Komponente, die Benutzereingaben verarbeitet, Zustände verwaltet oder auf Ereignisse reagiert, ist ein Framework-Island – keine .astro-Datei.

CSS Modules werden für das gesamte Komponenten-Styling verwendet – immer in einer separaten Datei styles.module.css, niemals inline oder innerhalb des Astro <style>-Blocks.

Wann dieses Skill verwendet werden sollte

  • Strukturierung eines neuen Astro-Projekts oder Hinzufügen von Seiten und Layout-Bereichen
  • Erstellen von .astro-Seiten, Layouts oder statischen präsentativen Bereichen
  • Entscheidung, ob etwas zu Astro oder zu einem SolidJS/React-Island gehört
  • Auswahl der geeigneten Hydrationsdirektive für ein Island
  • Anwendung von CSS Modules-Styling innerhalb von .astro-Dateien oder Framework-Islands
  • Arbeiten mit Content Collections (src/content/, src/content.config.ts)
  • Einspeisen von Service-Layer-Daten in serverseitig gerenderte Astro-Seiten
  • Verwenden von Server Islands (server:defer) für personalisierte, verzögerte Bereiche
  • Einrichtung von On-Demand-Rendering (SSR) mit Adaptern und Middleware
  • Definieren und Aufrufen von Astro Actions für typsichere serverseitige Mutationen

Astro vs. Islands – Die zentrale Architekturentscheidung

Dies ist die wichtigste Entscheidung in jedem Astro-Projekt.

Was es tutVerwendung
Rendert statisches HTML aus Daten – keine Benutzerinteraktion.astro
Seitenhülle, Layout-Wrapper, Navigationsstruktur.astro
Inhaltsbereiche, Blogbeiträge, Marketingbereiche.astro
Jede Komponente mit onClick, onChange, Formularzustand oder reaktiven DatenSolidJS- oder React-Island
Fundamentale UI-Komponenten (Button, Input, Modal, Alert, etc.)SolidJS- oder React-Island
Jede Komponente, die einen Store oder Service-Hook liest oder schreibtSolidJS- oder React-Island

Die Regel in einfachen Worten:

  • Astro rendert Struktur und Inhalt. Es verarbeitet keine Benutzerinteraktionen.
  • SolidJS oder React übernimmt die gesamte Interaktivität, den gesamten Formularzustand und alle fundamentalen interaktiven UI-Primitive – selbst einen einfachen Button, der ein Ereignis auslöst.
  • Erstelle keine interaktive UI in .astro-Dateien. Astro hat keine Reaktivität. Der Versuch, einer .astro-Datei Interaktivität hinzuzufügen, erzeugt fragilen, nicht testbaren Code.

Welches Framework – SolidJS oder React?

Das Projekt verwendet durchgängig eines. Überprüfe astro.config.mjs auf die konfigurierte Integration (@astrojs/solid-js oder @astrojs/react) und verwende dieses Framework für alle Islands im Projekt. Mische nicht beide Frameworks im selben Projekt.

Lies ./references/islands-and-hydration.md für den vollständigen Entscheidungsleitfaden und die Referenz zu Hydrationsdirektiven.

Styling-Regeln – CSS Modules in separaten Dateien

Dies ist die wichtigste Regel in diesem Skill.

Jede Astro-Komponente, -Seite und jedes -Layout verwendet CSS Modules für bereichsbezogenes Styling. Das CSS befindet sich in einer separaten Datei – niemals innerhalb des Astro <style>-Tags.

ComponentName/
├── index.astro         ← Komponentenlogik und Markup
└── styles.module.css   ← ALLE Styles für diese Komponente, immer eine separate Datei
  • Erstelle immer styles.module.css neben index.astro.
  • Setze niemals Styles innerhalb des Astro <style>-Blocks.
  • Verwende niemals Inline-style-Attribute.
  • Importiere das Modul oben im Frontmatter-Bereich: import styles from './styles.module.css'
  • Wende Klassen mit der class:list-Direktive oder direkter Klassenbindung an:
    • <div class={styles.container}>
    • <div class:list={[styles.container, isActive && styles.active]}>
  • Verwende semantische Klassennamen. Keine Stapelung von Utility-Klassen.
  • Verwende CSS-Custom-Properties für alle Design-Tokens (Farben, Abstände, Typografie).
  • Kein !important. Keine Deep-Selektoren. Keine ID-Selektoren für das Styling.

Lies ./references/styling-and-css-modules.md für die Token-Strategie, Theme-Variablen, responsive Regeln und Animationsanleitung. Lies ./examples/button-component/ für ein vollständiges Button-Beispiel mit separater CSS Module-Datei.

Projektstruktur

src/
├── components/
│   ├── foundation/         # Interaktive UI-Primitive – SolidJS oder React, NICHT .astro
│   │   ├── Button/
│   │   │   ├── index.tsx           ← SolidJS (.tsx) oder React (.tsx)
│   │   │   └── styles.module.css
│   │   └── Input/
│   │       ├── index.tsx
│   │       └── styles.module.css
│   ├── layout/             # Statische Layout-Struktur – .astro
│   │   ├── Header/
│   │   │   ├── index.astro
│   │   │   └── styles.module.css
│   │   └── Footer/
│       ├── index.astro
│       └── styles.module.css
│   └── features/           # Interaktive Funktionsbereiche – SolidJS oder React
│       └── SomeFeature/
│           ├── index.tsx           ← Island-Komponente
│           └── styles.module.css
├── layouts/
│   └── BaseLayout/
│       ├── index.astro             ← Layout-Hülle ist immer .astro
│       └── styles.module.css
├── pages/
│   ├── index/
│   │   ├── index.astro             ← Seite ist immer .astro
│   │   └── styles.module.css
│   └── [dynamic]/
│       ├── index.astro
│       └── styles.module.css
├── content/
│   ├── blog/
│   └── [collection-name]/
├── content.config.ts   ← Astro 5 Collection-Schemas und Loader
├── store/
│   ├── repository/
│   ├── service/
│   └── config.ts
├── styles/
│   ├── tokens/
│   │   ├── _colors.css
│   │   ├── _spacing.css
│   │   └── _typography.css
│   ├── global.css
│   └── themes/
│       ├── light.css
│       └── dark.css
└── utils/

Namenskonventionen:

  • .astro-Seiten und -Layouts: PascalCase/-Ordner mit index.astro
  • Framework-Island-Komponenten: PascalCase/-Ordner mit index.tsx
  • Seiten: kebab-case/-Ordner mit index.astro oder [dynamic]/ mit index.astro
  • CSS Module-Dateien: immer styles.module.css – eine pro Komponentenverzeichnis
  • Hilfsfunktionen: kebab-case.ts

Lies ./references/project-structure.md für eine vollständige Aufschlüsselung der Verzeichnisverantwortlichkeiten und Namenskonventionen.

Astro-Komponentenform

.astro-Dateien dienen nur der statischen Struktur. Sie rendern HTML aus Props und Daten – sie verarbeiten keine Ereignisse und verwalten keine Zustände.

  • Verwende typisierte Props mittels interface Props im Frontmatter-Bereich.
  • Greife auf Props mit Astro.props zu.
  • Halte Komponenten klein und auf eine Aufgabe ausgerichtet.
  • Bevorzuge Komposition gegenüber Prop-Drilling.
  • Halte Ausdrücke einfach; verlagere komplexe Logik in Frontmatter-Variablen.
  • Verwende semantische HTML-Elemente – <section>, <article>, <nav>, <main>, <header> – anstelle generischer <div>-Wrapper, wenn das Element eine semantische Bedeutung hat.
---
import styles from './styles.module.css'

interface Props {
  title: string
  subtitle?: string
}

const { title, subtitle } = Astro.props
---

<section class={styles.hero} aria-label={title}>
  <h1 class={styles.title}>{title}</h1>
  {subtitle && <p class={styles.subtitle}>{subtitle}</p>}
  <slot />
</section>

Lies ./references/component-patterns.md für Frontmatter-Konventionen, Slot-Verwendung und Astro-API-Referenz.

Fundamentale Komponenten – SolidJS oder React, nicht Astro

Fundamentale UI-Primitive (Button, Input, Alert, Modal, Select, Toggle, etc.) werden immer als SolidJS- oder React-Komponenten erstellt. Sie sind niemals .astro-Dateien.

Warum: Fundamentale Komponenten verarbeiten Benutzerereignisse, verwalten den Fokus, stellen onClick- und onChange-Callbacks bereit und halten manchmal interne Zustände. Nichts davon ist in einer .astro-Datei möglich. Das Erstellen eines „Buttons“ als .astro erzeugt statisches HTML, das nicht in einer typisierten, wiederverwendbaren Weise auf Klicks reagieren kann.

Die Entscheidungsregel:

  1. Primitiv existiert – verwende es.
  2. Primitiv ist nah dran, aber es fehlt ein Prop – erweitere das bestehende Primitiv.
  3. Primitiv existiert nicht – erstelle es als SolidJS- oder React-Komponente in components/foundation/, bevor du es verwendest. Integriere niemals einmalige interaktive Elemente in Seiten- oder Feature-Komponenten.

Alle fundamentalen Komponenten müssen konsistent, zugänglich und stark typisiert sein. Lies das Skill solid.js oder react für die Implementierungskonventionen, die innerhalb von Island-Komponenten gelten.

Islands und Hydration

Jede interaktive Komponente ist ein Island. Mounte Islands aus .astro-Seiten und -Layouts mit einer client:*-Direktive. Wähle die minimale Direktive, die die Interaktionsanforderung erfüllt.

DirektiveWann verwenden
client:loadMuss sofort beim Seitenladen interaktiv sein
client:idleKann warten, bis der Browser im Leerlauf ist
client:visibleMuss nur hydrieren, wenn es in den Viewport kommt
client:media="(query)"Nur bei einer bestimmten Viewport-Größe interaktiv
client:only="solid-js" oder client:only="react"Benötigt Browser-APIs beim Rendern; SSR überspringen

Standardmäßig client:visible oder client:idle verwenden. Verwende client:load nur für UI, mit der der Benutzer sofort interagiert – primäre Formulare, Navigations-Dropdowns, Auth-Seiten.

Island-Komponenten haben immer ihr eigenes styles.module.css:

components/features/ContactForm/
├── index.tsx          ← SolidJS- oder React-Island
└── styles.module.css  ← separates CSS Module, gleiche Regel wie überall sonst

Mounten eines Islands von einer Astro-Seite:

---
import styles from './styles.module.css'
import ContactForm from '../../components/features/ContactForm/index.tsx'

const { prefillEmail } = Astro.props
---

<section class={styles.section}>
  <h2 class={styles.heading}>Kontaktiere uns</h2>
  <ContactForm client:visible prefillEmail={prefillEmail} />
</section>

Lies ./references/islands-and-hydration.md für den vollständigen Entscheidungsleitfaden, frameworkspezifische Hinweise und Regeln zur Datenübergabe.

Content Collections

Content Collections sind die kanonische Methode, um Markdown-, MDX- und strukturierte Datendateien mit vollständiger TypeScript-Typsicherheit zu verwalten.

Wichtige Änderungen in Astro 5:

  • Die Konfiguration befindet sich unter src/content.config.ts (nicht src/content/config.ts)
  • Collections verwenden einen loader – glob() oder file() aus astro/loaders
  • render(entry) ist eine Funktion, die aus astro:content importiert wird (nicht entry.render())
  • Importiere z aus astro:content, nicht direkt aus zod
// src/content.config.ts
import { defineCollection, z, reference } from 'astro:content'
import { glob } from 'astro/loaders'

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 }

Rendern in einer Seite:

---
import { getEntry, render } from 'astro:content'
const post = await getEntry('blog', Astro.params.slug)
const { Content } = await render(post)
---
<Content />

Lies ./references/content-collections.md für die vollständige API: Loader, Cross-Collection-Referenzen, benutzerdefinierte Loader, Runtime-Collections und dynamische Routenmuster.

Server Islands, SSR und Actions

Server Islands (server:defer)

Verschiebe eine personalisierte oder dynamische .astro-Komponente, während die Seitenhülle sofort ausgeliefert wird. Erfordert einen Adapter.

<UserCart server:defer>
  <span slot="fallback">···</span>
</UserCart>

Die verzögerte Komponente wird serverseitig ausgeführt und gestreamt. Verwende sie für benutzerspezifische UI (Warenkorb-Anzahl, Benachrichtigungen, personalisierte Begrüßungen), die sonst die statische Seitenauslieferung blockieren würde.

On-Demand-Rendering (SSR)

Optiere Seiten für serverseitiges Rendern mit export const prerender = false (Hybridmodus) oder setze output: 'server' global.

SSR-Seiten haben Zugriff auf Astro.cookies, Astro.request, Astro.redirect() und Astro.locals (befüllt durch Middleware).

Middleware

Definiere request-abfangende Logik in src/middleware.ts:

import { defineMiddleware } from 'astro:middleware'

export const onRequest = defineMiddleware(async (context, next) => {
  context.locals.user = await getUser(context.cookies.get('session')?.value)
  return next()
})

Astro Actions

Typsichere Serverfunktionen, definiert in src/actions/index.ts, aufrufbar von Islands oder HTML-Formularen:

// src/actions/index.ts
import { defineAction, ActionError } from 'astro:actions'
import { z } from 'astro:content'

export const server = {
  newsletter: {
    subscribe: defineAction({
      input: z.object({ email: z.string().email() }),
      handler: async ({ email }) => {
        await addSubscriber(email)
        return { success: true }
      },
    }),
  },
}

Aufruf von einem Island:

import { actions } from 'astro:actions'
const { data, error } = await actions.newsletter.subscribe({ email })

Verwende isInputError(error), um Zod-Validierungsfehler von Handler-Fehlern zu unterscheiden.

Lies ./references/server-rendering.md für die vollständige Abdeckung: Rendermodi, Adapterkonfiguration, Middleware, Server Islands, On-Demand-APIs, Actions mit Formularen, Fehlercodes, typisierte Umgebungsvariablen (astro:env) und View Transitions.

Astro-API-Referenz

  • Astro.props – typisierte Komponenten-Props
  • Astro.params – dynamische Routenparameter ([slug], [...path])
  • Astro.request – serverseitiges Request-Objekt (Header, Cookies, URL)
  • Astro.url – aktuelle Seiten-URL
  • getStaticPaths() – Pfade für die statische Seitenerzeugung aufzählen
  • getEntry() / getCollection() – Content Collection-Abfragen

Service-Layer-Datenfluss

Astro-Seiten und -Layouts sind der richtige Ort, um Service- oder Repository-Funktionen im Frontmatter-Bereich aufzurufen. Komponenten sollten Daten als Props erhalten.

  • Rufe Daten im Seiten-Frontmatter ab, nicht innerhalb von Komponenten.
  • Gib Daten als typisierte Props nach unten weiter.
  • Komponenten dürfen keine Repositories oder externen APIs direkt aufrufen.
  • Halte Validierung und Geschäftslogik im Service-Layer.

Barrierefreiheit

  • Verwende semantische HTML-Elemente, wo immer das Element eine Bedeutung hat.
  • Füge ARIA-Attribute hinzu, wo sie echte semantische Informationen liefern.
  • Stelle sicher, dass alle interaktiven Elemente zugängliche Namen haben.
  • Halte sichtbare Fokus-Zustände aufrecht.
  • Halte eine Mindestberührungszielgröße von 44px für interaktive Elemente ein.
  • Respektiere prefers-reduced-motion.
  • Strukturiere Überschriften logisch (h1 → h2 → h3) innerhalb des Seiteninhalts.

Lies ./references/accessibility-patterns.md für ARIA-Muster, Formularbeschriftungen und Anleitung zur Überschriftenhierarchie.

Unterstützende Dateien

  • ./references/styling-and-css-modules.md CSS Module-Regeln,

Verwandte Skills