Astro & Static Sites

Astro mit Claude Code: Static Sites & Islands Architecture 2026

Astro 5 kombiniert das Beste aus Static Generation und Server Rendering — Claude Code macht den Einstieg zum Kinderspiel.

📅 6. Mai 2026 ⏱ 10 min Lesezeit 🚀 Astro 5.x

Inhaltsverzeichnis

  1. Astro 5 Grundlagen — Setup & Komponenten-Syntax
  2. Islands Architecture — Framework-Inseln im HTML-Ozean
  3. Content Collections — Type-safe Inhalte mit Zod
  4. Server Actions & SSR — Dynamik wo sie gebraucht wird
  5. View Transitions — Flüssige Navigation ohne SPA-Overhead
  6. Deployment — Vercel, Netlify & Lighthouse 100

Astro hat in wenigen Jahren die Welt der Web-Entwicklung auf den Kopf gestellt. Mit dem revolutionären Islands-Ansatz liefert Astro Websites aus, die standardmäßig kein JavaScript zum Browser senden — und trotzdem React, Svelte, Vue oder Solid einbinden können, genau dort, wo Interaktivität wirklich gebraucht wird. 2026 ist Astro 5 die erste Wahl für Content-heavy Sites, Marketing Pages, Blogs und Dokumentationen.

Claude Code versteht die Astro-Philosophie und kann innerhalb von Sekunden vollständige Projekte scaffolden, Komponenten refaktorieren und Performance-Bottlenecks identifizieren. In diesem Guide zeigen wir, wie das Duo Astro + Claude Code die Entwicklung von Static Sites 2026 neu definiert.

Warum Astro 2026? Lighthouse-Score 100/100 out of the box, Zero-JS by default, native TypeScript, Content Collections mit Zod-Schemas, Server Islands für hybrides Rendering — und eine der aktivsten Communities im JS-Ökosystem.

1 Astro 5 Grundlagen — Setup & Komponenten-Syntax

Der Einstieg in Astro ist bewusst einfach gehalten. Mit einem einzigen Befehl entsteht ein produktionsreifes Projekt-Skelett — inklusive TypeScript-Konfiguration, ESLint und optionalen Integrationen.

Projekt erstellen mit Claude Code

Claude Code führt den Setup-Prozess vollautomatisch durch und fragt bei Unklarheiten nach:

# Neues Astro-Projekt starten npm create astro@latest meine-website # Interaktive Auswahl im Terminal: Which template? › Minimal Use TypeScript? › Yes (strict) Install dependencies? › Yes Initialize git? › Yes # Integrationen nachträglich hinzufügen npx astro add react tailwind sitemap

Das erzeugte Projekt-Skelett ist minimal und sauber. Claude Code versteht die Verzeichnisstruktur sofort und kann gezielt in einzelne Bereiche eingreifen:

meine-website/ ├── src/ │ ├── components/ # Wiederverwendbare .astro Komponenten │ ├── layouts/ # Seiten-Layouts mit <slot /> │ ├── pages/ # File-based Routing (.astro, .md, .mdx) │ └── content/ # Content Collections (KW19+) ├── public/ # Statische Assets (favicon, fonts) ├── astro.config.mjs # Haupt-Konfiguration └── tsconfig.json # TypeScript strict mode

Die .astro Komponenten-Syntax

Astro-Komponenten verbinden HTML-Templates mit einem JavaScript-Frontmatter-Block, der beim Build auf dem Server ausgeführt wird. Das Ergebnis ist reines, statisches HTML — kein Runtime-Overhead.

--- # src/components/BlogCard.astro --- interface Props { title: string; excerpt: string; date: Date; slug: string; category: string; } const { title, excerpt, date, slug, category } = Astro.props; const formattedDate = date.toLocaleDateString('de-DE', { year: 'numeric', month: 'long', day: 'numeric' }); --- <article class="blog-card"> <span class="category-badge">{category}</span> <h2><a href={`/blog/${slug}/`}>{title}</a></h2> <p>{excerpt}</p> <time datetime={date.toISOString()}>{formattedDate}</time> </article> <style> /* Scoped CSS — gilt NUR für diese Komponente */ .blog-card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 24px; } .category-badge { background: #6366f1; color: white; padding: 2px 10px; border-radius: 12px; } </style>

Astro-Feature Scoped CSS ohne Build-Tool-Konfiguration

Jede .astro-Datei kann einen <style>-Block enthalten. Astro scopet die Styles automatisch auf die Komponente — kein CSS-Modules-Setup, kein BEM, keine Klassen-Konflikte. Im Build wird daraus ein minimiertes, kritisches CSS-Bundle.

astro.config.mjs — Die Schaltzentrale

import { defineConfig } from 'astro/config'; import react from '@astrojs/react'; import tailwind from '@astrojs/tailwind'; import sitemap from '@astrojs/sitemap'; import vercel from '@astrojs/vercel/serverless'; export default defineConfig({ site: 'https://meine-website.de', integrations: [ react(), tailwind({ applyBaseStyles: false }), sitemap(), ], output: 'static', // 'server' für SSR, 'hybrid' für Mix adapter: vercel(), image: { service: { entrypoint: 'astro/assets/services/sharp' }, }, vite: { plugins: [], } });

Vite unter der Haube

Astro nutzt Vite als Build-Tool — blitzschnelle HMR, Tree-Shaking und optimale Bundle-Sizes inklusive.

🔒

TypeScript strict

Props, Frontmatter und Content Collections sind vollständig typisiert. Claude Code versteht die Typen und schlägt korrekte Signaturen vor.

📁

File-based Routing

src/pages/blog/[slug].astro erzeugt automatisch dynamische Routen — konventionsbasiert, ohne Router-Konfiguration.

2 Islands Architecture — Framework-Inseln im HTML-Ozean

Islands React Svelte Vue

Das Herzstück von Astro ist die Islands Architecture: Die Seite wird als reines, statisches HTML ausgeliefert. Nur explizit markierte Komponenten — die "Inseln" — laden JavaScript nach und werden im Browser hydriert. Das Ergebnis: drastisch reduzierte Bundle-Sizes, schnellere Ladezeiten und bessere Core Web Vitals.

Das Prinzip: "Ship Zero JS by Default." Interaktivität ist opt-in, nicht opt-out. Während klassische SPAs den gesamten JavaScript-Bundle laden bevor irgendetwas sichtbar wird, zeigt Astro sofort den Inhalt und hydratisiert nur einzelne Komponenten auf Anforderung.

Hydration Directives — Kontrolle über das Wann

Astro bietet fünf Hydration-Direktiven, die steuern, wann und wie eine Komponente im Browser zum Leben erwacht:

--- # src/pages/index.astro import { Navbar } from '../components/Navbar.astro'; import KontaktFormular from '../components/KontaktFormular.tsx'; import Testimonials from '../components/Testimonials.svelte'; import LiveChat from '../components/LiveChat.vue'; import AnalyticsWidget from '../components/AnalyticsWidget.tsx'; --- <!-- Kein JS — wird als reines HTML gerendert --> <Navbar /> <!-- client:load — sofort hydrieren, höchste Priorität --> <KontaktFormular client:load /> <!-- client:idle — nach requestIdleCallback (non-critical) --> <LiveChat client:idle /> <!-- client:visible — erst wenn im Viewport (IntersectionObserver) --> <Testimonials client:visible /> <!-- client:media — nur wenn Media Query matched --> <AnalyticsWidget client:media="(min-width: 1024px)" /> <!-- client:only — nur client-side, kein SSR (z.B. window-abhängig) --> <LiveChat client:only="react" />

island React-Komponente in Astro einbinden

Framework-Komponenten funktionieren genau wie gewohnt — Props, Hooks, State alles inklusive. Astro kümmert sich um die Hydration-Infrastruktur.

// src/components/KontaktFormular.tsx — normale React-Komponente import { useState } from 'react'; interface FormData { name: string; email: string; nachricht: string; } export default function KontaktFormular() { const [formData, setFormData] = useState<FormData>({ name: '', email: '', nachricht: '' }); const [status, setStatus] = useState<'idle' | 'loading' | 'success'>('idle'); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setStatus('loading'); await fetch('/api/kontakt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData), }); setStatus('success'); } if (status === 'success') return <p>Danke! Wir melden uns bald.</p>; return ( <form onSubmit={handleSubmit}> <input value={formData.name} onChange={e => setFormData({...formData, name: e.target.value})} placeholder="Dein Name" /> <button type="submit" disabled={status === 'loading'}>Senden</button> </form> ); }

Performance-Vergleich: SPA vs. Islands

Metrik Next.js SPA Astro Islands Vorteil
Initial JS Bundle ~250 KB (gzip) ~0 KB 100%
Time to First Byte ~200ms ~40ms 5× schneller
Largest Contentful Paint ~2.1s ~0.6s 3.5× besser
Lighthouse Performance 65–80 95–100 +20 Punkte
React/Svelte/Vue Support ✓ (React native) ✓ (alle parallel) Astro flexibler

3 Content Collections — Type-safe Inhalte mit Zod

Collections Zod TypeScript

Content Collections sind Astros typisiertes CMS-System. Markdown- und MDX-Dateien werden mit Zod-Schemas validiert und stehen danach vollständig typisiert zur Verfügung. Keine Runtime-Fehler durch fehlende Frontmatter-Felder mehr.

Schema definieren

// src/content/config.ts — Zentrale Schema-Definitionen import { defineCollection, z } from 'astro:content'; const blogCollection = defineCollection({ type: 'content', schema: z.object({ title: z.string().min(10).max(100), description: z.string().max(200), publishDate: z.coerce.date(), updatedDate: z.coerce.date().optional(), author: z.string().default('SpockyMagicAI Team'), category: z.enum(['KI', 'Web', 'Tools', 'Tutorial']), tags: z.array(z.string()).default([]), draft: z.boolean().default(false), image: z.object({ src: z.string(), alt: z.string(), }).optional(), readTime: z.number().int().positive(), // Minuten }), }); const teamCollection = defineCollection({ type: 'data', schema: z.object({ name: z.string(), rolle: z.string(), bio: z.string(), avatar: z.string().url(), social: z.object({ twitter: z.string().optional(), github: z.string().optional(), }), }), }); export const collections = { blog: blogCollection, team: teamCollection, };

Inhalte abrufen und rendern

--- # src/pages/blog/index.astro import { getCollection } from 'astro:content'; import Layout from '../../layouts/BaseLayout.astro'; import BlogCard from '../../components/BlogCard.astro'; // Alle veröffentlichten Blog-Posts laden und sortieren const allPosts = await getCollection('blog', ({ data }) => { return !data.draft; // Drafts filtern }); const sortedPosts = allPosts.sort( (a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf() ); // Nach Kategorien gruppieren const byCategory = sortedPosts.reduce((acc, post) => { const cat = post.data.category; acc[cat] = [...(acc[cat] ?? []), post]; return acc; }, {} as Record<string, typeof sortedPosts>); --- <Layout title="Blog"> <div class="blog-grid"> {sortedPosts.map(post => ( <BlogCard title={post.data.title} excerpt={post.data.description} date={post.data.publishDate} slug={post.slug} category={post.data.category} /> ))} </div> </Layout>
--- # src/pages/blog/[slug].astro — Dynamische Post-Seite import { getCollection, getEntry } from 'astro:content'; export async function getStaticPaths() { const posts = await getCollection('blog'); return posts.map(post => ({ params: { slug: post.slug }, props: { post }, })); } const { post } = Astro.props; const { Content } = await post.render(); // Verwandte Posts laden const related = await getCollection('blog', ({ data, slug }) => data.category === post.data.category && slug !== post.slug ); --- <article> <h1>{post.data.title}</h1> <Content /> <!-- MDX/Markdown wird zu React-Komponenten --> </article>

Tipp Claude Code + Content Collections

Claude Code versteht Zod-Schemas und kann daraus automatisch TypeScript-Typen, Validierungslogik und sogar Test-Fixtures generieren. Beschreibe einfach die Datenstruktur in natürlicher Sprache: "Erstelle ein Schema für Blog-Posts mit Titel, Datum, Tags und optionalem Hero-Bild" — und Claude Code liefert den vollständigen, typsierten Collection-Code.

4 Server Actions & SSR — Dynamik wo sie gebraucht wird

SSR Actions API Routes

Astro 5 führt Server Actions als First-Class-Feature ein: typisierte, serverseitige Funktionen, die direkt aus Komponenten aufgerufen werden können. Kein Boilerplate für API-Routes mehr bei einfachen Formularen und CRUD-Operationen.

Hybrid Rendering: Mit output: 'hybrid' kann jede Seite individuell zwischen statischem und serverseitigem Rendering wählen. export const prerender = false macht eine einzelne Seite dynamisch, ohne den Rest der Site zu beeinflussen.

Server Actions definieren

// src/actions/index.ts import { defineAction } from 'astro:actions'; import { z } from 'astro:schema'; export const server = { newsletter: { subscribe: defineAction({ accept: 'form', input: z.object({ email: z.string().email('Ungültige E-Mail-Adresse'), vorname: z.string().min(2), }), handler async({ email, vorname }) { // Direkt Datenbankzugriff — kein separater API-Endpunkt nötig await db.insert(subscribers).values({ email, vorname, subscribedAt: new Date() }); await sendWelcomeEmail(email, vorname); return { success: true, message: `Willkommen, ${vorname}!` }; }, }), }, contact: { send: defineAction({ accept: 'json', input: z.object({ name: z.string(), email: z.string().email(), nachricht: z.string().min(20), betreff: z.enum(['Support', 'Partnerschaft', 'Presse']), }), handler async(data, context) { const ip = context.request.headers.get('x-forwarded-for'); await rateLimit(ip, 'contact', 5); // Max 5 pro Stunde await sendToSlack(data); return { ticket: crypto.randomUUID() }; }, }), }, };

Actions in Komponenten nutzen

--- # src/components/NewsletterForm.astro import { actions } from 'astro:actions'; // Progressive Enhancement: funktioniert auch ohne JS! const result = Astro.getActionResult(actions.newsletter.subscribe); --- <form method="POST" action={actions.newsletter.subscribe}> <input type="email" name="email" required placeholder="deine@email.de" /> <input type="text" name="vorname" required placeholder="Vorname" /> <button type="submit">Newsletter abonnieren</button> {result?.error && <p class="error">{result.error.message}</p>} {result?.data?.success && <p class="success">{result.data.message}</p>} </form>

API Routes für komplexe Anwendungsfälle

// src/pages/api/search.ts — REST-Endpunkt import type { APIRoute } from 'astro'; import { getCollection } from 'astro:content'; export const GET: APIRoute = async ({ request }) => { const url = new URL(request.url); const query = url.searchParams.get('q')?.toLowerCase() ?? ''; if (!query || query.length < 2) { return new Response( JSON.stringify({ error: 'Mindestens 2 Zeichen' }), { status: 400, headers: { 'Content-Type': 'application/json' } } ); } const posts = await getCollection('blog', ({ data }) => !data.draft); const results = posts.filter(post => post.data.title.toLowerCase().includes(query) || post.data.description.toLowerCase().includes(query) || post.data.tags.some(tag => tag.toLowerCase().includes(query)) ).slice(0, 10); return new Response(JSON.stringify(results.map(p => ({ slug: p.slug, title: p.data.title, description: p.data.description, }))), { headers: { 'Content-Type': 'application/json' } }); };

SSR Cookies & Session Management

Im SSR-Modus stellt Astro.cookies eine komfortable API für HTTP-Cookies bereit. Claude Code kann daraus vollständige Auth-Flows mit JWT-Tokens, Session-Cookies und CSRF-Protection generieren — in wenigen Minuten.

  • Astro.cookies.get('session')?.value — Cookie lesen
  • Astro.cookies.set('session', token, { httpOnly: true }) — Cookie setzen
  • Astro.redirect('/login') — Redirect bei fehlendem Auth

5 View Transitions — Flüssige Navigation ohne SPA-Overhead

View Transitions Animation ClientRouter

View Transitions sind einer der spektakulärsten Features moderner Webentwicklung — und Astro macht sie erschreckend einfach. Statt einer vollständigen SPA-Architektur nutzt Astro die native View Transitions API des Browsers für flüssige Seitenübergänge bei MPA-Sites.

ClientRouter aktivieren

--- # src/layouts/BaseLayout.astro — Einmalige Aktivierung im Layout import { ClientRouter } from 'astro:transitions'; --- <!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8" /> <ClientRouter /> <!-- Das ist alles! Navigation wird automatisch intercepted --> <title>{Astro.props.title}</title> </head> <body> <slot /> </body> </html>

Animationen mit transition:animate

--- # src/pages/blog/[slug].astro — Animierte Blog-Post-Seite import { fade, slide, morph } from 'astro:transitions'; --- <!-- Slide-In von rechts beim Öffnen eines Blog-Posts --> <main transition:animate="slide"> <h1 transition:animate={fade({ duration: '0.3s' })}> {post.data.title} </h1> <!-- Hero-Bild "morpht" nahtlos zwischen Listen- und Detail-Ansicht --> <img src={post.data.image?.src} transition:name={`hero-${post.slug}`} transition:animate="morph" /> </main>
--- # src/pages/blog/index.astro — Artikel-Liste mit passenden transition:name --- {allPosts.map(post => ( <article> <!-- Gleiches transition:name → Browser morpht das Bild beim Navigieren --> <img src={post.data.image?.src} transition:name={`hero-${post.slug}`} /> <h2><a href={`/blog/${post.slug}/`}>{post.data.title}</a></h2> </article> ))}

Persistente Inseln — Navigation ohne State-Verlust

<!-- Audio-Player bleibt bei Navigation aktiv --> <PodcastPlayer client:load transition:persist transition:name="podcast-player" /> <!-- Warenkorb bleibt ohne State-Reset --> <Warenkorb client:idle transition:persist="warenkorb" />

Kompatibilität Graceful Degradation

Die View Transitions API wird von modernen Browsern unterstützt (Chrome 111+, Safari 18+, Firefox 130+). Astros ClientRouter implementiert automatisch einen Fallback für ältere Browser — die Navigation funktioniert dann ohne Animationen, aber das Rendering bleibt korrekt.

Lifecycle Events: Astro feuert Custom Events während Transitions (astro:before-preparation, astro:after-swap, astro:page-load), mit denen Analytics-Tracking, A/B-Tests und progressive Enhancement sauber integriert werden können.

6 Deployment — Vercel, Netlify & Lighthouse 100

Vercel Netlify Image Optimization Lighthouse 100

Astro-Projekte lassen sich auf allen modernen Hosting-Plattformen deployen. Für die optimale Developer Experience empfehlen sich Vercel oder Netlify — beide bieten offizielle Astro-Adapter mit vollständiger Edge-Functions-Unterstützung.

Vercel Deployment

# 1. Adapter installieren npm install @astrojs/vercel # 2. astro.config.mjs anpassen import vercel from '@astrojs/vercel/serverless'; export default defineConfig({ output: 'server', adapter: vercel({ imageService: true, // Vercel Image Optimization nutzen edgeMiddleware: true, // Middleware auf Edge laufen lassen isr: { // Incremental Static Regeneration expiration: 60 * 60, // 1 Stunde Cache }, }), }); # 3. Deployen npx vercel --prod

Netlify mit Edge Functions

# Netlify Adapter npm install @astrojs/netlify import netlify from '@astrojs/netlify'; export default defineConfig({ output: 'server', adapter: netlify({ edgeMiddleware: true, cacheOnDemandPages: true, }), }); # netlify.toml — Erweiterte Cache-Strategie [[headers]] for = "/blog/*" [headers.values] Cache-Control = "public, max-age=3600, stale-while-revalidate=86400"

Astro Image — Automatische Bildoptimierung

--- # Astro:assets — Eingebaute Bildoptimierung import { Image, Picture } from 'astro:assets'; import heroImage from '../../assets/hero.jpg'; --- <!-- Automatisch: WebP-Konvertierung, srcset, lazy loading, korrekte Dimensionen --> <Image src={heroImage} alt="Astro Framework Hero" width={1200} height={630} format="webp" quality={85} loading="eager" /> <!-- Responsive Bildformat-Set für verschiedene Viewports --> <Picture src={heroImage} formats={['avif', 'webp', 'jpeg']} alt="Hero Bild" widths={[400, 800, 1200]} />

Lighthouse 100 — Checkliste

Performance Was Astro automatisch richtig macht

  • Critical CSS inlining: Astro extrahiert und inlinet das kritische CSS automatisch
  • Script Bundling: Nur das JS, das tatsächlich genutzt wird, wird gebundelt
  • Preload hints: Fonts, Bilder und Scripts werden mit korrekten <link rel="preload"> versehen
  • Zero-layout-shift: astro:assets setzt width/height automatisch (kein CLS)
  • Kompression: Vercel/Netlify aktivieren Brotli/gzip automatisch
# Lokaler Lighthouse-Test vor dem Deploy npm install -g lighthouse # Production Build starten npm run build && npm run preview # Lighthouse CLI ausführen lighthouse http://localhost:4321 \ --only-categories=performance,accessibility,best-practices,seo \ --output=html \ --output-path=./lighthouse-report.html # Ziel: Performance ≥ 95, Accessibility = 100, SEO = 100

CI/CD Pipeline mit GitHub Actions

# .github/workflows/deploy.yml name: Deploy to Vercel on: push: branches: [main] pull_request: branches: [main] jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20' } - run: npm ci - run: npm run build - run: npm run test - name: Deploy to Vercel if: github.ref == 'refs/heads/main' env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} run: npx vercel --prod --token=$VERCEL_TOKEN
🌐

Edge Deployment

Mit @astrojs/vercel/edge läuft jede Seite am nächsten PoP — globale Latenz unter 50ms möglich.

🖼️

Image CDN

Vercel Image Optimization und Cloudinary-Integration wandeln Bilder on-demand in WebP/AVIF um — mit automatischem Caching.

📊

Analytics

Vercel Analytics und Web Vitals Monitoring lassen sich mit zwei Zeilen Code in jedes Astro-Projekt einbinden.

Fazit — Warum Astro + Claude Code 2026 unschlagbar ist

Astro 5 hat den Static-Site-Generator-Markt neu definiert. Mit Islands Architecture, Content Collections, Server Actions und View Transitions bietet es die Performance von statischen Sites bei der Flexibilität moderner Web-Frameworks. Die Lernkurve ist flach, die Entwicklerergonomie exzellent.

Claude Code beschleunigt die Astro-Entwicklung dramatisch: Komponenten werden aus Natürlichsprache-Beschreibungen generiert, Schemas automatisch typisiert, Performance-Probleme sofort identifiziert. Der Workflow von der Idee zur Produktion schrumpft von Tagen auf Stunden.

Ob Marketing-Seite, Blog, Dokumentation oder hybride Web-App — Astro ist 2026 die technisch überlegene Wahl, und Claude Code der perfekte Entwicklungspartner dafür.

Quick Start mit Claude Code: Öffne Claude Code, tippe "Erstelle ein Astro 5 Projekt mit TypeScript, Tailwind, Content Collections für Blog-Posts und einer React-Island für das Kontaktformular" — und lehne dich zurück.

Bereit, mit Astro & Claude Code zu starten?

Starte deine kostenlose Trial und erlebe, wie Claude Code komplette Astro-Projekte in Minuten scaffoldet, refaktoriert und deployed — ohne Copy-Paste, ohne Dokumentation wälzen.

Kostenlose Trial starten →