Zum Hauptinhalt springen
Alle Beiträge

CMS zu Astro hinzufügen mit Keystatic und Cloudflare Pages

· 3 Min. Lesezeit ·

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:

  1. GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
  2. 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
  3. Registrieren → Client ID notieren
  4. Client Secret generieren → sofort kopieren (wird nur einmal angezeigt)

Schritt 2 — Cloudflare KV Namespace für Sessions

Keystatic speichert Session-Tokens in Cloudflare KV:

  1. Cloudflare Dashboard → Workers & Pages → KV
  2. Namespace anlegen, z.B. your-site-sessions
  3. 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):

VariableWert
NODE_ENVproduction
GITHUB_REPO_OWNERGitHub-Benutzername
GITHUB_REPO_NAMERepository-Name
KEYSTATIC_GITHUB_CLIENT_IDaus Schritt 1
KEYSTATIC_GITHUB_CLIENT_SECRETaus Schritt 1

In Pages → Settings → Functions → KV namespace bindings:

VariablennameKV Namespace
SESSIONder 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 gespeichertGITHUB_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.

Mehr zum Thema

Sehen Sie, was eine moderne Astro-Website für Ihr Unternehmen leisten kann, transparent kalkuliert.

Mehr erfahren