🔄 Update April 2026: Fallstrick 10 ergaenzt — R2 Media-Upload, CSRF-Header und der korrekte Upload-Weg via EmDash-Admin. Ausserdem: R2 Public-URL konfiguriert (pub-d1d7f5f57ea747fcb4c0d5bae0b1d227.r2.dev).
🔄 Laufend aktualisiert. Dieser Artikel wird kontinuierlich um neue Erkenntnisse und Fallstricke ergänzt. Zuletzt aktualisiert: April 2026.

Sprache: 🇩🇪 Deutsch | 🇬🇧 English version

Dieser Artikel entstand direkt aus der Praxis – inklusive aller Debugging-Erkenntnisse, die wir erst durch echtes Ausprobieren herausgefunden haben.

Die Ausgangssituation

April 2026. Ziel: Eine moderne, KI-native Website fuer ein AI-Magazin. Die Wahl fiel auf EmDash, Cloudflares neues Open-Source-CMS als spirituellen Nachfolger von WordPress – serverless, sicher, KI-nativ. 75 Minuten, echter Stress, echte Loesungen. Dieser Artikel dokumentiert alles.

Die ehrliche Kostenrechnung

Component / Komponente$/Monat
Domain automatedweb.net (Cloudflare)~1
Cloudflare Workers Paid Plan5
R2, D1, SSL, CDN0 (inklusive / included)
Gesamt / Total~6

Monatliche Gesamtkosten: ~6 $ pro Monat. WordPress-Managed-Hosting: 15-50 $/Monat.

Schritt 1: Domain bei Cloudflare kaufen

Domain direkt bei Cloudflare registrieren – dann sind Domain und Workers-Hosting im selben Dashboard, keine DNS-Konfiguration noetig. .com war nur mit Bindestrich verfuegbar (automated-web.com) – ein No-Go. .net ist die sauberste Alternative.

Schritt 2: EmDash installieren

npm create emdash@latest

Setup-Wizard: Projektname → Cloudflare Workers (D1+R2) → Starter → npm. Ca. 2 Minuten.

⚠️ Fallstrick #1: Bestaetigung mit y erforderlich

npm fragt: Ok to proceed? (y). Nur Enter druecken → npm error canceled. Nochmal starten, y eingeben.

Schritt 3: Lokal testen

cd automatedweb && npm run dev

Admin unter http://localhost:4321/_emdash/admin. Site-Titel setzen, Passkey anlegen (kein Passwort!), Sample-Content aktivieren.

Schritt 4: Cloudflare vorbereiten

4a: R2 aktivieren

R2 einmalig im Cloudflare Dashboard aktivieren. Kreditkarte zur Verifikation noetig, die ersten 10 GB sind kostenlos.

⚠️ Fallstrick #2: worker_loader braucht den Paid Plan

Ohne Workers Paid Plan ($5/Monat) schlaegt der Deploy fehl:

binding LOADER of type worker_loader is invalid [code: 10021]

Kein Workaround. Paid Plan aktivieren, dann erneut deployen.

Schritt 5: Deployen

npm run deploy

Browser oeffnet sich fuer Cloudflare OAuth. Nach Login laeuft alles automatisch.

⚠️ Fallstrick #3: KV Namespace existiert bereits [code: 10014]

Wenn ein frueherer fehlgeschlagener Versuch Ressourcen angelegt hat:

a namespace with this account ID and title already exists [code: 10014]

Loesung: Cloudflare Dashboard → Workers & Pages → KV → Namespace my-emdash-site-session loeschen → erneut deployen.

⚠️ Fallstrick #4: wrangler.jsonc wird ignoriert

Die manuelle KV-ID in wrangler.jsonc hat keine Wirkung – npm run deploy nutzt intern --experimental-provision und ueberschreibt die Config. Einzige Loesung: Namespace loeschen, neu erstellen lassen.

Erfolgreicher Deploy:

🎉 All resources provisioned, continuing with deployment...
Deployed my-emdash-site triggers (6.41 sec)
https://my-emdash-site.yourname.workers.dev

Schritt 6: Custom Domain verbinden

Cloudflare Dashboard → Workers & Pages → Projekt → Settings → Custom Domains → Add. Sofort aktiv, keine Wartezeit.

⚠️ Fallstrick #5: Produktions-Datenbank ist leer

Das lokale Setup gilt nicht fuer die Live-Seite. Setup zweimal durchfuehren: lokal + live.

Schritt 7: KI-Integration via MCP

  1. Admin auf der Live-URL oeffnen (nicht localhost!)
  2. Settings → API Tokens → neuen Token erstellen
  3. Claude Desktop Config bearbeiten: %APPDATA%\Claude\claude_desktop_config.json
  4. EmDash als MCP-Server eintragen, Claude Desktop neu starten

⚠️ Fallstrick #6: Token muss von der Live-URL erstellt werden

Das hat uns am meisten Zeit gekostet. Ein Token von localhost:4321 gilt nur lokal. Auf der Live-Seite kommt:

{"error":{"code":"INVALID_TOKEN","message":"Invalid or expired token"}}

Loesung: Token immer auf der eigenen Live-Domain erstellen.

⚠️ Fallstrick #7: Die richtige EmDash API-Struktur

Korrekter API-Pfad: /_emdash/api/content/posts (nicht /admin/posts)

Data-Wrapper erforderlich bei POST und PATCH:

// Falsch / Wrong - 400 VALIDATION_ERROR:
{ title: "Post", content: "..." }

// Richtig / Correct - 201:
{ data: { title: "Post", content: "..." } }

Ohne den Wrapper: 400 VALIDATION_ERROR – kein Hinweis auf den fehlenden Wrapper in der Fehlermeldung.

Unsere Empfehlungen

Domain direkt bei Cloudflare kaufen – spart DNS-Konfiguration komplett
Workers Paid Plan sofort aktivieren – ohne ihn laeuft EmDash nicht in Produktion
R2 vor dem ersten Deploy aktivieren – sonst schlaegt Deploy fehl
Bei KV-Fehlern: Namespace loeschen, neu deployen
API-Token immer auf der Live-URL erstellen – nicht auf localhost
data-Wrapper bei API-Calls nicht vergessen – { data: { ...fields } }
Starter-Template waehlen – maximale Flexibilitaet

FAQ

Brauche ich Programmierkenntnisse?

Grundlegende Terminal-Kenntnisse reichen. Befehle kopieren und ausfuehren – echten Code schreiben nicht noetig.

Kann ich von WordPress zu EmDash migrieren?

EmDash unterstuetzt WordPress WXR-Exporte. Es gibt ein EmDash Exporter Plugin. Custom Post Types erfordern manuelle Nacharbeit.

Was passiert wenn meine Seite viral geht?

Workers Paid inkludiert 10 Mio. Requests/Monat, dann 0,30 $ pro weitere Million. Automatische Skalierung.

Warum gibt der MCP-Server 404 zurueck obwohl der Token stimmt?

Der API-Pfad ist falsch. Korrekt: /_emdash/api/content/posts. Ausserdem brauchen POST/PATCH den data-Wrapper.

Ist EmDash production-ready?

Seit April 2026 verfuegbar – fuer neue Projekte sehr gut geeignet. Fuer kritische Business-Websites noch 6-12 Monate warten.

Funktioniert EmDash fuer mehrsprachige Websites?

Noch keine eingebaute i18n. Unsere Loesung: Slugs mit Sprachkuerzel (artikelname-de / articlename-en) und Sprach-Tags.

Fazit

75 Minuten. 6 Dollar pro Monat. Eine moderne, KI-native, global gehostete Website mit MCP-Server, Passkey-Login und automatischer Skalierung – ohne eigenen Server. EmDash und Cloudflare Workers ist die ueberzeugendste Option fuer neue Projekte, die wir aktuell kennen.

Fallstrick 10: Media-Upload – R2, CSRF und der richtige Weg

Das hat uns am laengsten beschaeftigt. Bilder hochladen sollte einfach sein – ist es bei EmDash auf Cloudflare Workers aber nicht out-of-the-box.

Das Problem: NOT_SUPPORTED

Der POST /media/upload-url Endpoint gibt NOT_SUPPORTED zurueck:

{ "error": { "code": "NOT_SUPPORTED", "message": "Storage does not support signed upload URLs. Use direct upload." } }

Ursache: Das native R2-Binding (@emdash-cms/cloudflare) unterstuetzt keine Pre-Signed URLs – das ist ein Design-Entscheid von EmDash. Uploads muessen durch den Worker gehen.

Die Loesung: Drei Schritte

Schritt 1 – R2 Public Access aktivieren:

npx wrangler r2 bucket dev-url enable my-emdash-media
# → https://pub-XXXXX.r2.dev

Schritt 2 – publicUrl in astro.config.mjs eintragen:

storage: r2({ binding: "MEDIA", publicUrl: "https://pub-XXXXX.r2.dev" })

Schritt 3 – Rebuild + Deploy:

npm run build && npm run deploy

Der CSRF-Bypass fuer API-Uploads

Externe POST-Requests werden von Cloudflare mit 403 blockiert. Der korrekte Header laut EmDash-Quellcode (src/api/csrf.ts):

headers: {
  "Authorization": "Bearer TOKEN",
  "X-EmDash-Request": "1",   // ← Das ist der Magic Header
  ...form.getHeaders()
}

Dieser Header signalisiert EmDash, dass es sich um einen legitimen internen Request handelt. Browser koennen ihn cross-origin nicht setzen – deshalb ist er sicher als CSRF-Schutz.

Fuer externe Scripts (z.B. vom lokalen PC)

Node.js-Skripte koennen den Header problemlos setzen. Wichtig: Den Request ohne Origin-Header senden – dann greift laut CSRF-Code die Server-to-Server-Ausnahme.

Dieser Fallstrick hat uns mehrere Stunden gekostet – weil die Fehlermeldung irreführend war und wir durch mehrere Schichten von Cloudflare WAF, EmDash CSRF und R2-Binding-Logik navigieren mussten.

Dieser Artikel wurde von Claude direkt via MCP veroeffentlicht – nachdem wir gemeinsam alle Fallstricke debuggt hatten.