CMS zu Astro hinzufügen mit Keystatic und Cloudflare Pages
Die meisten CMS-Optionen für Astro fallen in zwei Kategorien: gehostete Services mit monatlichen Kosten und API-Rate-Limits (Contentful, Sanity, Storyblok), oder selbst gehostete Datenbanken, die einen eigenen Server benötigen. Keystatic ist keins von beiden.
Keystatic ist ein Git-basiertes CMS, das direkt in der bestehenden Astro-Site läuft. Inhalte werden als Markdown- und YAML-Dateien direkt im GitHub-Repository gespeichert. Keine separate Datenbank, kein separater Server, keine nutzungsbasierte Abrechnung. Die Editor-UI ist unter einer /keystatic-Route auf der eigenen Domain erreichbar und wird über GitHub OAuth authentifiziert. In der Entwicklung nutzt Keystatic lokalen Dateispeicher — keine Authentifizierung nötig, funktioniert direkt auf localhost.
Es ist eine gute Wahl für inhaltsreiche Sites, bei denen Kunden Texte und Bilder bearbeiten müssen, ohne Code zu berühren: Blog-Posts, Neuigkeiten, Produktbeschreibungen, Team-Seiten. Der Kompromiss ist eine 30–90-sekündige Rebuild-Verzögerung zwischen dem Speichern von Inhalten und dem Sichtbarwerden auf der Site — Keystatic committet nach GitHub, dann baut Cloudflare Pages automatisch neu. Wenn sofortige Aktualisierungen erforderlich sind, ist eine andere Architektur nötig.
Schritt 1 — GitHub OAuth App
Keystatic authentifiziert Produktionsnutzer über GitHub OAuth. Dafür muss eine OAuth App registriert werden:
- GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
- Ausfüllen:
- Application name:
Your Site CMS(beliebige Bezeichnung) - Homepage URL:
https://yourdomain.com - Authorization callback URL:
https://yourdomain.com/api/keystatic/github/oauth/callback
- Application name:
- Registrieren → Client ID notieren
- Client Secret generieren → sofort kopieren (wird nur einmal angezeigt)
Schritt 2 — Cloudflare KV Namespace für Sessions
Keystatic speichert Session-Tokens in Cloudflare KV:
- Cloudflare Dashboard → Workers & Pages → KV
- Namespace anlegen, z.B.
your-site-sessions - Namespace ID notieren
Schritt 3 — Keystatic installieren
pnpm add @keystatic/core @keystatic/astro
Die Admin-UI von Keystatic benötigt React, also auch @astrojs/react installieren, falls noch nicht vorhanden.
In astro.config.mjs:
import keystatic from '@keystatic/astro';
import react from '@astrojs/react';
export default defineConfig({
integrations: [react(), keystatic()],
output: 'hybrid', // Keystatic benötigt SSR für die /keystatic-Route
adapter: cloudflare(),
});
Wichtig: Keystatic erfordert output: 'hybrid' oder output: 'server'. Mit einem vollständig statischen Build ist es nicht kompatibel.
keystatic.config.ts im Projekt-Root anlegen:
import { config, fields, collection } from '@keystatic/core';
export default config({
storage: process.env.NODE_ENV === 'production'
? { kind: 'github', repo: 'github-username/repo-name' }
: { kind: 'local' },
collections: {
posts: collection({
label: 'Blog Posts',
slugField: 'title',
path: 'src/content/blog/*',
format: { contentField: 'content' },
schema: {
title: fields.slug({ name: { label: 'Titel' } }),
publishedDate: fields.date({ label: 'Veröffentlichungsdatum' }),
description: fields.text({ label: 'Beschreibung', multiline: true }),
content: fields.markdoc({ label: 'Inhalt' }),
},
}),
},
});
API-Route unter src/pages/api/keystatic/[...params].ts anlegen:
import { makeRouteHandler } from '@keystatic/astro/api';
import config from '../../../../keystatic.config';
export const { GET, POST } = makeRouteHandler({ config });
Schritt 4 — Umgebungsvariablen und KV Binding
In Cloudflare Pages → Settings → Environment variables (Production):
| Variable | Wert |
|---|---|
NODE_ENV | production |
GITHUB_REPO_OWNER | GitHub-Benutzername |
GITHUB_REPO_NAME | Repository-Name |
KEYSTATIC_GITHUB_CLIENT_ID | aus Schritt 1 |
KEYSTATIC_GITHUB_CLIENT_SECRET | aus Schritt 1 |
In Pages → Settings → Functions → KV namespace bindings:
| Variablenname | KV Namespace |
|---|---|
SESSION | der Namespace aus Schritt 2 |
Und in wrangler.toml:
[[kv_namespaces]]
binding = "SESSION"
id = "kv-namespace-id"
Schritt 5 — OAuth Callback URL aktualisieren
Nach dem ersten Deploy zurück zur GitHub OAuth App und beide Felder mit der echten Domain aktualisieren:
- Homepage URL:
https://yourdomain.com - Authorization callback URL:
https://yourdomain.com/api/keystatic/github/oauth/callback
Wenn das CMS auch auf Cloudflare Pages Preview-URLs zugänglich sein soll, eine zweite Callback-URL hinzufügen: https://yoursitename.pages.dev/api/keystatic/github/oauth/callback
Fehlerbehebung
“Invalid binding SESSION” — Die KV-Namespace-Binding-Variable muss exakt SESSION heißen. Pages → Settings → Functions prüfen.
GitHub OAuth funktioniert nicht — Prüfen, ob die Callback-URL in der GitHub OAuth App exakt mit der deployed Domain übereinstimmt, inklusive https://. Außerdem sicherstellen, dass Umgebungsvariablen unter Production gesetzt sind, nicht nur unter Preview.
Inhalte werden nicht gespeichert — GITHUB_REPO_OWNER und GITHUB_REPO_NAME müssen exakt mit dem Repository übereinstimmen, Groß-/Kleinschreibung beachten. Der verwendete GitHub-Account muss Schreibzugriff auf das Repository haben.
Build-Fehler nach Keystatic-Installation — Sicherstellen, dass output: 'hybrid' gesetzt und @astrojs/react installiert ist.
Lokale Entwicklung
pnpm dev
http://localhost:4321/keystatic aufrufen — in der Entwicklung ist keine Authentifizierung nötig. Keystatic nutzt lokalen Dateispeicher und speichert direkt ins Dateisystem.
Hinweise für Kundenprojekte
Keystatic ist kostenlos und Open Source. Kunden benötigen einen GitHub-Account für den Editor, oder man legt einen für sie an. Inhalte liegen im Repository als Dateien — einfach versionierbar, prüfbar und bei Bedarf migrierbar. Die /keystatic-Route ist nur für authentifizierte GitHub-Nutzer zugänglich. Für zusätzliche Absicherung kann Cloudflare Access (Zero Trust) vorgeschaltet werden.
Sehen Sie, was eine moderne Astro-Website für Ihr Unternehmen leisten kann, transparent kalkuliert.
Mehr erfahren