Wer in EmDash bisher eine umfangreiche Seite mit vielen Inhaltsblöcken bearbeitet hat, kennt das Problem: Alle Eingabeformulare standen komplett aufgeklappt untereinander. Um einen einzigen Block zu verschieben, musste man erst endlos an den anderen vorbeiscrollen. Öffnete eine Kollegin zur selben Zeit denselben Beitrag, blieb ihr nur die Wahl zwischen «Schreibgeschützt öffnen» und «Übernehmen». Und schon für einfache System-Mails wie Benutzereinladungen oder Anmeldelinks benötigte EmDash ein separates Plugin.

EmDash 1.5 löst alle drei Probleme auf einmal. Mehrere Personen können denselben Beitrag gleichzeitig in Echtzeit bearbeiten, der neue Editor klappt Blöcke übersichtlich ein, und E-Mails verschickt das CMS jetzt direkt über SMTP. Hinzu kommen moderne AVIF-Bilder sowie ein eingebauter Staging-Modus für neu aufgesetzte Websites: Er sorgt automatisch dafür, dass halbfertige Seiten und Beispielinhalte nicht in Suchmaschinen wie Google auftauchen (noindex), solange die Website noch im Aufbau ist und niemand bewusst auf Go live geklickt hat.

Seit EmDash 1.4 sind 312 Commits von rund 40 Mitwirkenden zusammengekommen. Viele davon beheben ganz konkrete Probleme aus dem Alltag: Tabellen im Admin ragten auf dem Smartphone über den Bildschirmrand hinaus, Weiterleitungen mit Umlauten liefen ins Leere, passwortgeschützte WordPress-Beiträge standen nach einem Import plötzlich öffentlich im Netz, und durch ein neues Abfragelimit bei Cloudflare D1 konnten Datenbank-Backups grosser Websites abbrechen.

Die wichtigsten Neuerungen von EmDash 1.5 im Überblick:

Funktion

Was sie bringt

PR

Echtzeit-Co-Editing

Mehrere Personen arbeiten live im selben Eintrag (optional aktivierbar)

#4695

Neuer Block-Editor

Blöcke starten eingeklappt, gelöschte Blöcke lassen sich wiederherstellen

#4573

Sichere Revisionen

Automatisches Speichern (Autosave) überschreibt keine manuellen Versionen mehr

#4637

Eigene Seitenleisten

Jede Person sortiert Hauptnavigation und Editor-Seitenleiste für sich selbst

#4628

formats für <Image>

Direkte Ausgabe von AVIF und WebP über das HTML-Element <picture>

#3307

Schlanke Platzhalter

Blurhash-Berechnung aus 64 Pixeln Vorschau statt aus 24-Megapixel-Originalen

#4213

Staging-Modus

Neue Websites bleiben für Suchmaschinen auf noindex, bis sie live gehen

#3716

Nativer SMTP-Versand

System-Mails ohne Zusatz-Plugin versenden, auch auf Cloudflare Workers

#2156

Konfigurationsprüfung

Ungültige Optionen brechen den Build gezielt ab, statt wirkungslos zu bleiben

#4641

Vier dieser Funktionen habe ich selbst beigesteuert: die formats-Erweiterung für Bilder, den Staging-Modus, die SMTP-Anbindung und die Prüfung der Konfiguration. Die grösste Neuerung dieses Releases stammt jedoch von Noah Pham.

Der EmDash-Editor aus Sicht von Lena Brunner. Oben rechts stehen drei Avatare: Lena Brunner, Jonas Keller und Mira Steiner. Lena tippt im zweiten Absatz, im dritten zeigt ein farbiger Cursor mit Namen, wo Jonas Keller schreibt, und im letzten Absatz schreibt Mira Steiner.
Drei Personen, ein Beitrag: Lena sieht, wo Jonas und Mira gerade schreiben, jeweils mit Namen und eigener Farbe. Ihr Text erscheint, während sie tippen.

Echtzeit-Co-Editing in EmDash: Gemeinsam am selben Beitrag arbeiten

Bisher setzte EmDash beim Öffnen eines Eintrags eine exklusive Bearbeitungssperre. Wer denselben Beitrag danach öffnete, konnte ihn entweder nur lesen oder die Sperre hart übernehmen – und warf damit die andere Person aus dem Editor. Für eine Redaktion, in der zwei Leute gemeinsam an einem Artikel feilen oder gegenlesen, ist das unpraktisch.

Mit #4695 können nun mehrere Personen gleichzeitig im selben Eintrag arbeiten. Oben im Editor erscheinen die Avatare aller Anwesenden, in Formularen ist markiert, in welchem Feld jemand gerade klickt, und im Fliesstext (Rich Text) wandert der farbige Cursor samt Namen live mit. Gleichzeitige Textänderungen führt EmDash automatisch zusammen, und Rückgängig nimmt ausschliesslich die eigenen Schritte zurück. Gespeichert wird gemeinsam – unter Berücksichtigung derselben Rollenrechte, Validierungen, Hooks und Revisionen wie bisher. Auch Änderungen von aussen, etwa über die REST-API, MCP, die CLI, den visuellen Editor oder durch Plugins, tauchen ohne Neuladen sofort in allen geöffneten Editoren auf.

Standardmässig ist das gemeinsame Bearbeiten noch deaktiviert. Einschalten lässt es sich explizit in der astro.config.mjs:

js
emdash({
	coEditing: true,
});

Technisch wird das je nach Hosting unterschiedlich gelöst: Auf Cloudflare verwaltet ein sogenanntes Durable Object mit integriertem SQLite-Speicher jede aktive Bearbeitungssitzung als eigenen digitalen Raum, über den sich alle Browser in Echtzeit synchronisieren. Neue Websites aus den offiziellen Startvorlagen bringen diese Einrichtung bereits fertig mit. Wie schnell EmDash wird, wenn die ganze Website in einem Durable Object läuft, habe ich in EmDash in einem Durable Object gemessen. Bestehende Projekte ergänzen in ihrer wrangler.jsonc ein Binding sowie den passenden Export:

jsonc
"durable_objects": { "bindings": [{ "name": "EMDASH_ROOMS", "class_name": "EmDashRoom" }] },
"exports": { "EmDashRoom": { "type": "durable-object", "storage": "sqlite" } },

Zusätzlich müssen im eigenen Worker-Code die Klassen EmDashRoom und EmDashRoomSite aus @emdash-cms/cloudflare/worker exportiert werden. Fehlt das Binding, fällt EmDash sicher auf die bisherige Bearbeitungssperre zurück. Auf Node.js läuft das Co-Editing direkt im Serverprozess (#4668). Wichtig ist dort nur: Ein Betrieb über mehrere node:cluster-Worker wird nicht unterstützt, da der Sitzungsstatus im Prozessspeicher liegt, und ein vorgeschalteter Reverse Proxy muss WebSocket-Verbindungen durchlassen. Alle Einrichtungsdetails stehen in der Dokumentation für Cloudflare und Node.js.

Besonders beruhigt hat mich ein Detail im Changeset: Für normale Seitenbesucher im Frontend verursacht Co-Editing keine einzige zusätzliche Datenbankabfrage – völlig egal, ob die Funktion ein- oder ausgeschaltet ist. Die Live-Räume werden erst dann aktiv und kosten Ressourcen, wenn tatsächlich jemand im Admin einen Beitrag öffnet.

Einige technische Grenzen im Alltag sollte man dennoch kennen:

  • Bei einfachen Formularfeldern ausserhalb von Rich Text setzt sich bei zeitgleicher Bearbeitung eine der beiden Änderungen durch. Lediglich bei Autorenangaben (Bylines), Verweisen (Referenzen) und Taxonomie-Begriffen (wie Kategorien oder Schlagwörtern) werden paralleles Hinzufügen und Entfernen sauber zusammengeführt.
  • Wandelt jemand einen Inhaltsblock in einen anderen Typ um, verschiebt oder löscht ihn, während eine andere Person gerade darin schreibt, gehen deren ungespeicherte Eingaben in diesem Block verloren.
  • Änderungen, die sich bei einem Konflikt nicht automatisch zusammenführen lassen, gehen nicht verloren, sondern werden als separate Wiederherstellungs-Revision im Versionsverlauf abgelegt.
  • Wer eigene Hooks einsetzt, die vor dem Speichern Benutzerrollen prüfen, sollte ab sofort alle Beteiligten im Feld editedBy kontrollieren – und nicht mehr nur die einzelne Person, die den Speichern-Knopf gedrückt hat.

Ich habe das Co-Editing an einer Testkopie mit zwei Benutzerkonten durchgespielt: Der Cursor des Gegenübers erscheint mit Namen im Absatz, getippte Sätze bauen sich live auf, und nach wenigen Sekunden war der gemeinsame Stand für beide gespeichert.

Neuer Block-Editor: Mehr Übersicht auch bei langen Seiten

Auf längeren Seiten verlor man im bisherigen Editor schnell die Orientierung, weil jeder einzelne Block sämtliche Eingabefelder dauerhaft offen anzeigte – selbst dann, wenn man an einer ganz anderen Stelle arbeitete. Noah Pham hat den Block-Editor deshalb von Grund auf überarbeitet. Statt durch endlose Formulare zu scrollen, blickt man nun zuerst auf die Struktur der Seite.

Alle Blöcke starten eingeklappt. Jede Zeile zeigt kompakt ein passendes Symbol, den Blocknamen, einen kurzen Textauszug sowie ein Vorschaubild. So erfasst man den Seitenaufbau auf einen Blick, ohne ein einziges Feld aufklappen zu müssen. Aktionen wie Verschieben, Duplizieren und Löschen sind ordentlich ins ⋯-Menü gewandert. Wer versehentlich einen Block löscht, holt ihn einfach mit Rückgängig zurück. Umsortieren klappt per Drag-and-Drop mit der Maus oder barrierefrei per Tastatur über Alt+Umschalt+Pfeiltaste.

Im EmDash-Block-Editor sind mehrere Inhaltsblöcke eingeklappt. Das Aktionsmenü eines Blocks ist geöffnet.
Der neue Block-Editor: Alle Blöcke starten eingeklappt, Verschieben, Duplizieren und Löschen liegen im Menü.

Klappt man einen Block auf, stehen die eigentlichen Inhaltsfelder klar getrennt über den Darstellungs-Einstellungen. Listen innerhalb eines Blocks lassen sich wahlweise als einfache Aufzählung, als Tabelle oder als aufklappbare Elemente bearbeiten. Zudem prüft EmDash Eingaben jetzt schon direkt im Admin vor dem Speichern: Die Validierung nutzt exakt dieselben Regeln wie der Server und markiert Fehler unmittelbar am betroffenen Feld.

Ein geöffneter Block im EmDash-Editor. Die Inhaltsfelder stehen oben, die Einstellungen darunter.
Ein aufgeklappter Block: oben der Inhalt, darunter die Einstellungen zur Darstellung.

Für bestehende Websites ist der Umbau komplett schmerzfrei: Weder gespeicherte Datenbankinhalte noch API-Antworten oder das Frontend-Rendering ändern sich. Wer eigene Blocktypen aus älteren Marketing- oder Portfolio-Vorlagen übernommen hat, sieht dort lediglich so lange ein allgemeines Platzhalter-Symbol, bis in der Block-Definition ein icon hinterlegt wird. Nach welchen Feldnamen der Editor seine kompakte Vorschau zusammenstellt, erklärt die Anleitung zu Blöcken.

Verlässliche Versionsgeschichte: Autosave überschreibt keine gespeicherten Versionen mehr

Diesen Fehler hätte ich lieber früher gekannt: Bisher überschrieb die automatische Zwischenspeicherung (Autosave) die jeweils jüngste Revision – selbst dann, wenn man diese kurz zuvor bewusst per Klick auf Speichern angelegt hatte. Wer also einen Stand gezielt sicherte, danach weiterschrieb und kurz pausierte, suchte seine manuell gespeicherte Fassung anschliessend vergeblich unter Revisionen.

Mit #4637 ersetzt ein Autosave ausschliesslich einen vorangegangenen Autosave. Alle bewusst gespeicherten Stände sowie automatisch von EmDash erzeugte System-Versionen bleiben dauerhaft erhalten. Zusätzlich protokolliert jede Revision nun sämtliche Personen, die seit der Vorversion am Eintrag mitgearbeitet haben – etwa in der Form «Ana, Ben und 1 weitere Person». Das bildet einerseits das Fundament für das Co-Editing, hilft Redaktionen aber auch ohne Live-Zusammenarbeit: Vor dem Veröffentlichen sieht man sofort, wer seit der letzten Live-Fassung noch Hand angelegt hat.

Die zugehörige Datenbank-Migration 096_revision_kind_and_editors fügt dafür zwei neue Spalten hinzu; ältere Bestands-Revisionen zeigen weiterhin ihren ursprünglichen Einzelautor. Eine technische Konsequenz sollte man dabei im Hinterkopf behalten: Sobald diese Migration durchgelaufen ist, können ältere EmDash-Versionen die Website per Site Transfer weder exportieren noch Daten in sie importieren.

Individuelle Seitenleisten im Admin für jedes Teammitglied

Unter Einstellungen → Seitenleisten kann ab sofort jede angemeldete Person selbst festlegen, welche Menüpunkte der Hauptnavigation und welche Boxen der Editor-Seitenleiste sichtbar sind und in welcher Reihenfolge sie stehen (#4628). Diese Einstellung gilt für alle Benutzerrollen und wird direkt im jeweiligen Benutzerkonto gespeichert – sie wandert also über Browsergrenzen hinweg mit, ohne die Ansicht für Kolleginnen und Kollegen zu verändern. Lediglich das Dashboard bleibt fest ganz oben verankert, und die Box «Veröffentlichen» im Editor lässt sich zwar verschieben, aber nicht ausblenden.

Die Seite «Seitenleisten» in den Einstellungen von EmDash. Einträge der Navigation lassen sich per Schalter ausblenden und per Griff umsortieren.
Einstellungen → Seitenleisten: Jede Person blendet Menüpunkte für sich aus und sortiert sie um.

Im Redaktionsalltag räumt das spürbar auf: Wer ausschliesslich Artikel schreibt, blendet Bereiche wie Weiterleitungen, Menüs oder Plugins einfach für sich aus. Möchte man bestimmte Punkte weiterhin zentral für das gesamte Projekt verbergen, funktioniert das nach wie vor über admin.hiddenNavItems aus EmDash 1.4. Durch die neue Einstellungsseite entfallen im Gegenzug die bisherigen Ziehgriffe direkt in der Editor-Seitenleiste; wer sich dort bereits eine eigene Sortierung zurechtgelegt hatte, startet einmalig wieder mit der Standardreihenfolge.

Passend dazu erhalten Benutzerkonten ohne eigenes Profilbild jetzt überall einen einheitlichen farbigen Avatar mit ihren Initialen (#4791). Gerade beim gemeinsamen Bearbeiten erkennt man dadurch sofort, wer sich im Dokument bewegt.

Mobiler EmDash-Admin: Bedienbare Tabellen, Dialoge und Editor auf dem Smartphone

Bis EmDash 1.5 ragten die Übersichtstabellen für Inhalte, Kommentare, Medien, Benutzer und Taxonomien auf schmalen Smartphone-Displays seitlich über den Rand hinaus. Dadurch lag auch das wichtige …-Aktionsmenü am Zeilenende ausserhalb des sichtbaren Bereichs. Wer unterwegs rasch einen Kommentar freigeben wollte, musste jedes Mal erst nach rechts wischen.

Noah Pham hat sämtliche Tabellen im Admin überarbeitet (#4494, #4520, #4527 und weitere). Fällt der verfügbare Platz unter 42rem (672 Pixel), blenden die Listen nachrangige Spalten automatisch aus und gruppieren Status, Sprache sowie Datum kompakt direkt unter dem Titel. Weil sich die Tabellen dabei über CSS Container Queries nach ihrer eigenen Containerbreite richten – und nicht starr nach der gesamten Bildschirmbreite –, wechselt auch ein Tablet bei geöffneter Seitenleiste sauber in die schmale Darstellung.

Die Kommentarliste im EmDash-Admin auf einem Handy. Status und Datum stehen unter dem Text, das Menü jeder Zeile ist erreichbar.
Die Kommentarliste auf dem Handy: Status und Datum rücken unter den Text, das Menü bleibt erreichbar.

Auf Mobilgeräten schieben sich Dialogfenster zudem jetzt griffgünstig vom unteren Bildschirmrand nach oben. Die damit verbundenen Bedienungsverbesserungen helfen aber genauso am Desktop:

  • Bisher blieb ein Speichern-Knopf oft kommentarlos ausgegraut, solange irgendwo ein Pflichtfeld leer war. Jetzt lässt er sich jederzeit anklicken und zeigt direkt an den fehlenden Feldern verständliche Hinweise an.
  • Bereits eingetippter Text geht nicht mehr verloren, wenn man versehentlich neben das Dialogfenster tippt oder es auf dem Smartphone nach unten wegwischt.
  • Beim Löschen oder Verwerfen schliesst sich der Dialog erst dann, wenn der Server die Aktion erfolgreich bestätigt hat. Schlägt die Anfrage fehl, bleibt der Dialog offen und zeigt die Fehlermeldung direkt an Ort und Stelle.
Ein Dialog im EmDash-Admin auf dem Handy. Nach dem Klick auf Speichern zeigt das leere Pflichtfeld einen Hinweis.
Speichern lässt sich jederzeit klicken. Fehlt etwas, steht der Hinweis direkt am Feld.

Auch der Beitrags-Editor selbst ist jetzt vernünftig auf dem Smartphone nutzbar (#4485): Statt einer seitlich scrollenden Formatierungsleiste ordnet sich die Werkzeugleiste als kompaktes vierspaltiges Raster an, und Speicherfehler erscheinen unübersehbar direkt unter der Kopfzeile.

Moderne Bildformate: AVIF und WebP direkt über die Image-Komponente

Um Bilder platzsparend als AVIF und WebP auszuliefern, musste ich bisher auf Astros eigene <Picture>-Komponente ausweichen und mir die Bilddaten aus der EmDash-Mediathek dafür erst umständlich aufbereiten.

Mit Version 1.5 entfällt dieser Umweg. Ich habe die EmDash-Komponente <Image> um die Eigenschaft formats erweitert (#3307). Damit lassen sich die gewünschten Zielformate direkt als Array übergeben:

astro
<Image
	image={post.data.featured_image}
	width={1200}
	height={675}
	formats={["avif", "webp"]}
/>

EmDash generiert daraus automatisch ein standardkonformes `<picture>`-Element: Moderne Browser laden im obigen Beispiel die kleinere AVIF-Datei, alle übrigen greifen auf WebP zurück.

Lässt man formats weg, verhält sich <Image> exakt wie bisher. Werden Bilder über externe Medien-CDNs eingebunden, entscheidet weiterhin der jeweilige Dienstleister über das ausgelieferte Dateiformat. Weitere Beispiele finden sich in der Anleitung zur Mediathek.

Schnellerer Bildupload: Blurhash-Platzhalter ohne hohe CPU-Last

Beim Hochladen eines Bildes berechnet EmDash automatisch einen weichen Farbverlauf (Blurhash) sowie die dominante Hauptfarbe, die später beim Laden der Seite als sanfter Platzhalter dienen. Bisher hat der Server dafür jedes Mal die komplette Originaldatei dekodiert. Auf einem serverlosen Cloudflare Worker ein 24-Megapixel-Foto im Speicher zu entpacken, nur um daraus eine verschwommene Vorschau und einen Farbwert abzuleiten, verbraucht unnötig viel Rechenzeit.

Ab EmDash 1.5 erzeugt schon der Browser im Admin beim Upload ein winziges Vorschaubild von höchstens 64 Pixeln Kantenlänge und schickt es gleich mit – der Server rechnet anschliessend nur noch auf Basis dieser Miniatur (#4213). Als schöner Nebeneffekt erhalten nun erstmals auch hochgeladene WebP- und AVIF-Dateien solche Platzhalter, während freigestellte PNGs mit Transparenz keinen farbigen Hintergrund mehr bekommen, der ungewollt durch durchsichtige Bereiche schimmert. Wer selbst diese minimale Rechenzeit komplett einsparen möchte, schaltet die Funktion mit imagePlaceholders: false ganz ab.

Cloudflare D1 Backups: Zuverlässige Sicherungen trotz 50-MB-Abfragelimit

Am 30. Oktober hat Cloudflare angekündigt, dass seine serverlose SQLite-Datenbank D1 ab dem 4. November einzelne SQL-Abfragen ablehnt, deren Datenpaket grösser als 50 MB ausfällt. Als Schutzlimit für die Plattform ist das vernünftig – für EmDash barg es jedoch ein akutes Problem: Für Datenbank-Backups aus dem Admin sowie für Vorschau-Snapshots las das CMS bisher jede Datenbanktabelle in einem einzigen grossen Rutsch aus.

Sobald eine Tabelle – etwa durch tausende Beiträge oder eine lange Revisionshistorie – die 50-MB-Marke überschritt, brach der Backup-Download schlicht mit einem Fehler ab.

Ich habe die Ankündigung rechtzeitig gesehen und den passenden Fix geschrieben (#4610), der pünktlich zum Inkrafttreten der Sperre am 4. November gemergt wurde. EmDash liest sämtliche Tabellen beim Sichern nun seitenweise in kleineren Paketen aus. Dadurch bleibt jede einzelne Datenbankabfrage sicher unter dem Limit, während die fertige Backup-Datei exakt dieselben Daten enthält wie zuvor. Einstellen muss man dafür nichts.

Dennoch ersetzt ein Admin-Download kein vollständiges Sicherungskonzept. Welche Bausteine ich darüber hinaus einsetze, habe ich im Artikel Backups bei EmDash zusammengefasst.

Staging-Modus, nativer SMTP-Versand und Konfigurationsprüfung für Agenturen

Wenn Agenturen Kundenprojekte aufsetzen, kosten drei Dinge regelmässig Extrazeit: die Website während der Aufbauphase vor Suchmaschinen zu verbergen, den Versand von System-Mails einzurichten und Flüchtigkeitsfehler in der Konfiguration zu suchen. EmDash 1.5 bringt für alle drei Aufgaben saubere Bordmittel mit. Wann sich der Umstieg für Agenturen sonst lohnt, steht in EmDash statt WordPress?.

Staging-Modus: Neue Websites vor Google schützen bis zum Go-Live

Der EmDash-Admin zeigt den Staging-Status und erklärt, dass Suchmaschinen bis zum Go live ausgesperrt sind.
Neue Websites starten im Staging-Modus und bleiben für Suchmaschinen auf noindex, bis jemand auf Go live klickt.

Bisher war jede frisch installierte EmDash-Website ab der ersten Minute für Suchmaschinen indexierbar. Wer nicht sofort daran dachte, die SEO-Einstellungen oder die robots.txt anzupassen, fand halbfertige Kundenseiten oder «Hello World»-Beispiele schnell im Google-Index wieder.

Mit #3716 startet deshalb jede Website, die neu über den Einrichtungsassistenten oder die Setup-API angelegt wird, automatisch im Staging-Modus. Anders als bei einer separaten Staging-Serverumgebung geht es hier gezielt um die Sichtbarkeit in Suchmaschinen:

  • Alle Seiten, deren Template <EmDashHead> einbindet, geben im HTML-Kopf automatisch <meta name="robots" content="noindex, nofollow"> aus. Diese Regel hat Vorrang vor individuellen Angaben aus dem SEO-Panel oder aus Plugins. (Eigene Templates ohne <EmDashHead> erhalten das Tag allerdings nicht automatisch.)
  • Die Datei /robots.txt behält im Staging-Modus bewusst ihren normalen Inhalt und wird mit Cache-Control: no-store ungecacht ausgeliefert. Das ist entscheidend: Würde man Suchmaschinen schon in der robots.txt aussperren, dürften ihre Crawler die Seiten gar nicht erst abrufen – und würden den noindex-Hinweis niemals zu Gesicht bekommen.
  • Oben in der Kopfleiste des Admins erinnert ein gelbes Staging-Abzeichen jederzeit daran, dass Suchmaschinen noch ausgesperrt sind.

Ist die Website bereit für den Start, klickt ein Administrator unter Einstellungen → Allgemein im Abschnitt zum Website-Status auf Go live (alternativ per Settings-API oder MCP). Falls nötig, lässt sich eine Seite dort später auch wieder zurück in den Staging-Modus schalten.

Wichtig zum Verständnis: Der Staging-Modus ist kein Passwortschutz und keine Zugriffssperre. Wer die direkte URL kennt – etwa Kundinnen und Kunden bei der Abnahme –, kann jede Seite ganz normal im Browser aufrufen. Bestehende Live-Websites bleiben beim Update auf 1.5 unangetastet, und weder ein Site Transfer noch emdash export-seed überschreiben den Status einer Ziel-Website.

E-Mail-Versand per SMTP ohne zusätzliches Plugin

Für den Versand von System-E-Mails war in EmDash bisher zwingend ein Plugin nötig. Ab sofort genügt jeder beliebige Standard-SMTP-Server – egal ob Brevo, Microsoft 365 / Office 365, Amazon SES oder ein eigener Postfix-Mailserver, und zwar auch direkt auf Cloudflare Workers (#2156). Hinterlegen lassen sich die Zugangsdaten bequem im Admin unter Einstellungen → E-Mail oder über Umgebungsvariablen. Das SMTP-Passwort wird verschlüsselt in der Datenbank abgelegt; Voraussetzung dafür ist ein gesetzter EMDASH_ENCRYPTION_KEY. Praktisch bei der Fehlersuche: Schlägt eine Test-Mail fehl, zeigt EmDash jetzt die genaue Rückmeldung des Mailservers an statt bloss eines vagen «fehlgeschlagen». Alle Konfigurationswege beschreibt die Anleitung zu E-Mail.

Die SMTP-Einstellungen im EmDash-Admin: Server, Port, Verschlüsselung und Absender lassen sich ohne Plugin eintragen.
SMTP direkt im Admin unter Einstellungen → E-Mail, ohne Plugin.

Automatische Prüfung der Konfiguration in astro.config.mjs

Tippfehler oder falsche Datentypen in der astro.config.mjs fielen bisher oft gar nicht auf: Schreibweisen wie mcp: "yes" oder maxUploadSize: "10MB" nahm EmDash stillschweigend entgegen, ignorierte sie aber komplett. Ab 1.5 brechen astro dev und astro build bei ungültigen Werten sofort mit einer klaren Fehlermeldung ab, die die betroffenen Optionen beim Namen nennt (#4641). Bei leicht vertippten Optionsnamen wie sitUrl gibt EmDash eine gezielte Warnung samt Korrekturvorschlag aus. Gut möglich also, dass ein bisher scheinbar fehlerfreier Build direkt nach dem Update einmalig anhält – bis solche unbemerkten Altlasten bereinigt sind.

Neue Optionen für Entwickler bei Sammlungen, Seeds und Plugins

  • Sortierung nach Systemdaten: Im Admin lassen sich Inhaltslisten nun direkt nach Veröffentlichungsdatum, Erstellungsdatum oder letzter Änderung sortieren. Sammlungen können dafür unmittelbar auf publishedAt, createdAt oder updatedAt zugreifen, ohne dass man ein redundantes eigenes Datumsfeld anlegen muss (#4730).
  • Zeitsteuerung abschalten: Benötigt eine Sammlung keine geplanten Veröffentlichungen, lässt sich die Funktion gezielt per no-scheduling deaktivieren (#4729).
  • Lokale Seed-Bilder: Mediendateien für Seed-Daten müssen nicht mehr über eine öffentliche URL abrufbar sein, sondern lassen sich mit $media.file direkt aus dem lokalen Projektverzeichnis einlesen (#4728).
  • Bedingte Plugin-Panels: Plugins können über isVisible dynamisch steuern, unter welchen Bedingungen ihre Eingabebereiche im Editor eingeblendet werden (#4731).

Wichtige Bugfixes: WordPress-Migration, Weiterleitungen und D1-Performance

Neben den grossen Funktionen stecken in EmDash 1.5 zahlreiche Fehlerbehebungen für den Umzug von WordPress, für Sonderzeichen-URLs, Datenbankabfragen und das Frontend.

WordPress-Import und Migration

  • Passwortgeschützte Beiträge landeten öffentlich im Netz (#4742, Daniel): Beim Import einer WordPress-XML-Datei (WXR) wurden mit Passwort geschützte Beiträge bisher als regulär veröffentlichte Artikel übernommen – für alle sichtbar. Ab 1.5 legt EmDash sie sicher als Entwurf an und führt sie am Ende des Imports eigens auf. Wichtig für alle, die schon vor 1.5 Daten aus WordPress importiert haben: Im alten WordPress unter Beiträgen, Seiten und eigenen Inhaltstypen den Filter «Passwortgeschützt» prüfen und diese Einträge in EmDash manuell auf Entwurf zurückstellen. Das gilt ebenso für Umzüge über das EmDash-Exporter-Plugin, da dieses keine Passwörter überträgt – woran sich auch mit 1.5 nichts ändert.
  • Navigationsmenüs fehlten beim WXR-Import (#4666): Sie werden beim XML-Import jetzt regulär mitgenommen.
  • Doppelte Gastautoren alle 30 Beiträge (#4601): Umfangreiche Importe werden schrittweise in Paketen verarbeitet – und bisher legte jedes Paket dieselbe Gast-Byline erneut an.
  • Mehrspaltige Layouts und Cover-Blöcke verloren beim Import sämtliche Inhalte bis auf den reinen Text (#4603). Jetzt bleiben alle darin verschachtelten Blöcke erhalten.
  • Der CLI-Befehl `emdash import wordpress` existiert jetzt tatsächlich (#3765): Die offizielle Anleitung zur WordPress-Migration verwies bereits auf diesen Befehl, obwohl die CLI ihn noch gar nicht kannte. Er konvertiert eine WXR-Exportdatei lokal in JSON-Dateien, lädt Mediendateien herunter, erstellt eine Weiterleitungsliste und macht nach einem Abbruch dank --resume nahtlos weiter. Direkt in die Datenbank schreibt das Werkzeug nichts; diesen Schritt übernimmt weiterhin der Importer im Admin. Ganz nebenbei gibt emdash --version nun die echte Versionsnummer statt v0.0.0 aus.
  • Texte aus dem klassischen WordPress-Editor verschmolzen bisher zu einem einzigen riesigen Absatz (#4602). Jetzt trennt der Importer sauber an Leerzeilen.
  • Menülinks auf eigene Inhaltstypen (Custom Post Types) wie team-member gingen beim Umzug über das EmDash-Exporter-Plugin verloren (#4592, Daniel). Bereits importierte Menüs kann das Update rückwirkend nicht reparieren; fehlende Verweise müssen dort einmalig neu gesetzt werden.
  • WordPress-Buttons kamen bisher als starrer Block an, der sich im Editor nicht mehr anpassen liess (#4595). Jetzt bietet er ein reguläres Formular für Beschriftung, Ziel-URL und Stil jedes Buttons, und über /buttons lassen sich jederzeit neue anlegen.
  • Erstellungsdaten von WordPress-Entwürfen gingen beim Import verloren (#4709): Veröffentlichte man einen mitgenommenen Entwurf später in EmDash, erhielt er das aktuelle Tagesdatum und dadurch oft eine veränderte Permalink-URL. Nun bleibt das ursprüngliche Datum aus WordPress erhalten.
  • Markdown-Importe über API, CLI und MCP bewahren jetzt verschachtelte Formatierungen, Links sowie tiefere Listenebenen (#4607). GitHub-Flavored-Markdown-Tabellen (GFM) werden in echte Tabellenblöcke übersetzt und beim Export wieder sauber als Markdown ausgegeben. Beachten sollte man eine Änderung beim Umbruchverhalten: Ein einfacher Zeilenumbruch erzeugt jetzt einen weichen Umbruch innerhalb desselben Absatzes; für einen neuen Absatz ist eine Leerzeile nötig.

Weiterleitungen und URL-Slugs

  • Weiterleitungen mit Umlauten oder Sonderzeichen (wie tschechischen Háčeks) griffen bisher überhaupt nicht (#4615): Aufrufe wie /stitek/domácí-zvířata endeten immer mit einem 404-Fehler – ganz gleich, ob man die Regel im Klartext oder prozentkodiert hinterlegt hatte. Jetzt funktionieren beide Schreibweisen zuverlässig. Wer Software nur mit englischen URLs testet, übersieht solche Fehler leicht.
  • Unnötige Weiterleitungen bei unveröffentlichten Entwürfen (#4445, Daniel): Änderte man den Slug eines Beitrags, der noch nie live war, legte EmDash trotzdem eine Weiterleitung für eine URL an, die draussen niemand kennen konnte. Das unterbleibt jetzt.
  • Lange Schlagwort-Slugs auf Cloudflare D1 (#4098): War der URL-Slug eines Taxonomie-Begriffs bereits vergeben und mindestens 49 Zeichen lang, quittierte D1 den Versuch, eine fortlaufende Nummer anzuhängen, mit dem Datenbankfehler LIKE or GLOB pattern too complex.
  • Automatische Weiterleitungen bei URLs mit abschliessendem Schrägstrich (#4697): Endete das URL-Muster einer Sammlung auf / (etwa /whats-on/{slug}/), verwies die automatisch erzeugte Weiterleitung nach einer Slug-Änderung fälschlicherweise auf die Variante ohne Schrägstrich. Neue Regeln übernehmen den Schrägstrich nun korrekt, und bestehende Weiterleitungen greifen für beide Varianten.
  • Feinere API-Berechtigungen für Weiterleitungen (#4061): Statt pauschal den vollen admin-Scope zu verlangen, genügen für API-Tokens nun content:read zum Auslesen und settings:manage zum Bearbeiten von Weiterleitungen. Für den Abruf des 404-Protokolls (das Besucher-IP-Adressen enthält) reicht settings:read.

Weniger Datenbankabfragen auf Cloudflare D1 und SQLite

Bei Cloudflare D1 bedeutet jede einzelne Datenbankabfrage einen Netzwerkweg. Was EmDash auf Cloudflare wirklich bremst, habe ich in Kalter Cache statt Cold Start aufgeschlüsselt. Eine ganze Reihe von Optimierungen spart genau diese zusätzlichen Runden ein:

  • Keine Session-Abfrage ohne Cookie (#4726): Öffentliche Seiten fragten bisher bei jedem anonymen Seitenaufruf den Session-Speicher ab. Jetzt passiert das nur noch, wenn der Browser tatsächlich ein Session-Cookie mitschickt.
  • Schnellerer Kaltstart auf Workers (#4172): Startete ein frischer Worker-Isolate kalt, prüfte EmDash bisher erst in einer separaten Vorab-Abfrage den Migrationsstand und lud erst danach Einstellungen und Plugins. Jetzt läuft beides gebündelt im selben Batch – eine Datenbankrunde weniger bei nahezu jedem Kaltstart.
  • Gebündelter Object Cache (#4079): Eine Seite mit Beiträgen, Menüs, Autoren und Taxonomien prüft zur Cache-Validierung in der Regel nur noch einen gemeinsamen Schlüssel statt für jeden Bereich einen eigenen.
  • Beiträge ohne Taxonomie-Begriffe (#4088): Enthält eine Beitragsliste Artikel ohne zugewiesene Kategorien oder Schlagwörter, feuert EmDash dafür keine leeren Zusatzabfragen mehr ab.
  • Gezielter Cronjob für geplante Veröffentlichungen (#4560): Der Hintergrundprozess fragt nur noch jene Sammlungen ab, in denen tatsächlich ein Beitrag zur Veröffentlichung ansteht – statt pauschal jede Sammlung doppelt zu prüfen.
  • Autorenangaben (Bylines) mit Zusatzfeldern lädt EmDash nur noch einmal pro Seitenanfrage statt mehrfach für jede einzelne Beitragsliste (#4631). Davon profitieren vor allem Seiten mit mehreren getEmDashCollection()-Aufrufen oder «Ähnliche Beiträge»-Boxen.
  • Noch eine Abfrage weniger bei Bylines (#4727): Die Schema-Version eigener Byline-Felder wird nun direkt zusammen mit den Inhalten ausgelesen statt separat abgefragt.
  • Schlankere Imports beim Seitenstart (#4596): Bisher zog jeder Import aus dem Hauptpaket emdash im Hintergrund auch API-Schemas, den WordPress-Importer und die Seed-Logik in den Speicher, noch bevor die erste öffentliche Seite gerendert war. Jetzt werden diese Module erst nachgeladen, wenn Admin, API oder Importer sie wirklich aufrufen.
  • Schnellere Filter über mehrere Taxonomien (#3266): Kombinierte Filter beginnen ihre Suche jetzt automatisch bei der kleinsten Treffermenge statt starr beim ersten Eintrag in der where-Bedingung.
  • Index-Nutzung bei `where: { id: [...] }` (#3916): Solche Abfragen greifen nun zuverlässig über den Primärschlüssel zu. Zuvor durchsuchte SQLite nach einem ANALYZE-Lauf oft die komplette Tabelle, sobald Einträge im Papierkorb lagen.
  • Veraltete Daten im Object Cache behoben (#4651): Bei aktiviertem objectCache und vielen parallelen Lesezugriffen konnte sich nach einer Inhaltsänderung unter Umständen noch die alte Fassung im Cache festsetzen, bis erneut geschrieben wurde oder die Cache-Dauer ablief.

Verbesserungen im Admin und im Editor

  • Klare Beschriftung beim Anlegen: Bei einem neuen Eintrag heisst die Schaltfläche vor dem ersten Sichern jetzt unmissverständlich Entwurf speichern, und ein Hinweis in der Seitenleiste stellt klar, dass der Beitrag erst mit dem Veröffentlichen öffentlich sichtbar wird (#4640).
  • Ursprungszustand in den Revisionen (#4389, Daniel): Bisher speicherte EmDash erst die erste Änderung als erste Revision – die ursprüngliche Ausgangsfassung liess sich dadurch weder vergleichen noch wiederherstellen. Jetzt bleibt der Startzustand als älteste Version erhalten, auch bei Übersetzungen, Duplikaten und Importen.
  • Kein voreiliger Pflichtfeld-Alarm (#4385): Leere Pflichtfelder für Bilder, Dateien und Referenzen beschwerten sich bisher schon direkt beim Öffnen eines neuen Formulars mit «This field is required». Nun erscheint die Meldung erst beim Speichern und wird sauber an Screenreader übermittelt.
  • Fehlertoleranz bei defekten Datumsangaben (#4570): Ungültige Datumswerte aus Altbeständen oder Importen brachten Admin-Ansichten zum Absturz. Jetzt werden sie einfach als leeres Feld behandelt.
  • Zuverlässiger visueller Editor (#4484): Wurden auf einer Seite mehrere Einträge gleichzeitig im visuellen Editor angepasst, veröffentlicht er jetzt alle davon statt nur den ersten. Schlägt ein einzelner Eintrag fehl, bleiben die übrigen veröffentlicht.
  • Saubere Fehlermeldung für Nicht-Admins (#4717, Daniel): Riefen Redakteure ohne Admin-Rechte Bereiche wie Einstellungen, Benutzerverwaltung oder den WordPress-Import direkt per URL auf, landeten sie bisher auf halb geladenen oder nicht speicherbaren Seiten. Jetzt erscheint dort klar «Zugriff verweigert».
  • Rollenwechsel ohne Wartezeit (#4174, Daniel): Geänderte Benutzerrollen greifen ab sofort unmittelbar statt erst nach bis zu fünf Minuten Verzögerung.
  • Schutz vor versehentlichem Überschreiben (#4776): Aktualisierte sich der Editor im Hintergrund und setzte man anschliessend eigene ungespeicherte Eingaben zurück, konnte das darauffolgende Speichern fremde Änderungen überschreiben. EmDash erkennt und meldet diesen Konflikt nun.
  • Sichtbare Fehler bei geplanten Beiträgen (#4782): Scheiterte eine zeitgesteuerte Veröffentlichung – etwa an einem Validierungsfehler oder einem doppelt vergebenen Slug –, probierte es der Cronjob bisher endlos weiter und versteckte die Ursache im Server-Log. Jetzt stoppt EmDash die fehlerhafte Planung und weist direkt auf dem Admin-Dashboard mit der genauen Fehlermeldung darauf hin.
  • Kein doppeltes Laden beim Entwicklungsstart (#4593): Nach einem frischen Start von astro dev lud sich der Admin beim ersten Aufruf bisher einmal komplett neu, wodurch Plugin-Seiten mit veralteten Modulen weiterlaufen konnten.
  • Aktuelle Titel in Inhaltslisten (#4734): Bei Sammlungen mit aktivierten Revisionen zeigte die Übersichtstabelle nach dem Umbenennen eines unveröffentlichten Entwurfs noch den alten Titel an. Jetzt steht dort der aktuelle.
  • Sinnvolle Startansicht bei Formular-Einsendungen (#4521): Der Bereich öffnet nun direkt das Formular mit den jüngsten Eingängen statt eines neuen, leeren Formulars.
  • Stabile Wiederholungsfelder (Repeater): Sowohl leere Zeilen (#4479, Daniel) als auch Auswahlfelder (Select, #4625) verhalten sich in Repeatern jetzt wie erwartet.

Hinzu kommt Daniels umfangreiche Arbeit an der deutschen Sprachfassung: Zuerst übersetzte er Formulare und Weiterleitungen (#4545) sowie verbleibende englische «Not Found»-Meldungen (#4421), anschliessend alle übrigen Lücken (#4718). Damit ist die deutsche Oberfläche des EmDash-Admins jetzt vollständig übersetzt – ein Detail, das man auf Englisch gar nicht bemerkt, im deutschsprachigen Redaktionsalltag aber jeden Tag schätzt.

Korrekturen auf der öffentlichen Website

  • Sofort sichtbare Kommentar-Moderation trotz Cache (#4460): Freigegebene, moderierte oder gelöschte Kommentare leeren nun automatisch den Seitencache des betroffenen Beitrags, statt erst nach Ablauf der Cache-Zeit zu erscheinen.
  • Korrekte Sprache in mehrsprachigen Widgets (#4604): Widgets für Kategorien, Schlagwörter, neueste Beiträge und das Archiv fielen auf übersetzten Seiten auf die Standardsprache zurück. Jetzt zeigen sie die richtige Sprache, und übersetzte Beitrags-URLs folgen nun sauber dem Muster /en/posts/… statt /posts/en/….
  • Sinnvoller Fallback für externe Iframe-Embeds (#4696): Eingebettete Iframes von Drittanbietern abseits von YouTube oder Vimeo – beispielsweise aus WordPress übernommene Karten von Google My Maps – erschienen bisher als leerer Rahmen und verlinken stattdessen jetzt sauber auf die Originalquelle.
  • Sauberes Zusammenführen im JSON-LD-Schema (#3019): Da BlogPosting, publisher und WebSite bisher keine @id besassen, stand ein eigenes Organization-Schema im strukturierten Datengraphen als separates zweites Unternehmen neben dem Publisher. Wer ein eigenes Organisations-Schema ausgibt, sollte prüfen, dass dessen @id exakt dem Format <origin>/#organization entspricht (mit Schrägstrich vor der Raute), damit beide Einträge sauber verschmelzen.
  • Kein blockierendes Plugin-Admin-CSS im Frontend (#4482): Stylesheets aus dem adminEntry eines Plugins band der Produktions-Build bisher versehentlich als render-blockierende Ressource auf jeder öffentlichen Seite ein – ein unsichtbarer Bremsklotz für die Core Web Vitals.
  • Keine doppelten URLs im `srcset` (#4478): Gab Astros Bild-Service die Original-URL unverändert zurück, landete dieselbe Adresse mehrfach im srcset, auch im neuen <picture>-Element. Das ist behoben.
  • Lesbare Kommentare im Dark Mode (#4575): Comments und CommentForm besitzen unter .dark keine grellen Rahmen oder kontrastarmen Absende-Knöpfe mehr; die neuen Farbwerte lassen sich bei Bedarf über CSS-Variablen überschreiben.
  • Unterstützung für Astros `base`-Pfad (#4591): Läuft EmDash in einem Unterverzeichnis, berücksichtigen nun auch das Archiv- und Neueste-Beiträge-Widget sowie die hreflang-Verweise diesen Basispfad korrekt.
  • Eigene Medien-Domain auch für Logo und Favicon (#4284): Wer seine Mediendateien über eine eigene R2-Domain ausliefert, erhält diese CDN-URL jetzt konsequent auch für Website-Logo, Favicon und Social-Sharing-Bilder statt des internen Medienpfads.
  • Saubere TypeScript-Typen für Portable Text (#4662): Die Typdefinitionen aus emdash/ui lassen sich jetzt fehlerfrei auflösen, und <PortableText> validiert seine übergebenen Props. Wer dort fehlerhafte Werte übergibt, sieht diese nach dem Update beim Lauf von astro check.

Anmeldung, Sicherheit und Plugins

  • Datenbank-Aussetzer täuschen keinen Login-Fehler mehr vor (#4619): Ist bei einer externen Authentifizierung kurzzeitig die Datenbank nicht erreichbar, antwortet EmDash jetzt korrekt mit HTTP 503 (Service Unavailable) statt 401 (Unauthorized).
  • Cloudflare Access per Einmal-PIN (#4555): Anmeldungen ohne Gruppenzugehörigkeit scheitern bei aktivem roleMapping nicht mehr, sondern erhalten wie vorgesehen die definierte defaultRole.
  • Mehrere EmDash-Instanzen auf demselben Server (#4665): Liefen zwei EmDash-Projekte auf demselben Host, blockierten sich ihre Sandbox-Plugins bisher gegenseitig durch denselben fest reservierten Portbereich. Jetzt lässt EmDash freie Ports dynamisch vom Betriebssystem zuweisen.
  • Höheres Anfrage-Limit für Sandbox-Plugins (#4712): Pro Aufruf dürfen isolierte Plugins nun bis zu 30 statt bisher 10 Anfragen an Einstellungen, Speicher und Netzwerk stellen – was auf Cloudflare gleichzeitig dem Plattform-Maximum entspricht.
  • Sauber getrennte `uniqueIndexes` im Plugin-Speicher (#4715): Eindeutigkeitsregeln galten bisher versehentlich global über alle Plugins und Sammlungen hinweg, sodass ein Plugin Werte eines völlig anderen Plugins blockieren konnte. Die Migration 095_plugin_storage_unique_scope begrenzt bestehende Indizes sauber auf ihre jeweilige Sammlung.
  • Ehrliche Rückmeldung zur `robots.txt` über MCP (#4694): Besitzt ein Projekt eine eigene statische src/pages/robots.txt, lehnt die MCP-Schnittstelle Änderungen an seo.robotsTxt und seo.disallowAiTraining nun direkt ab, statt Erfolg für Einstellungen zu melden, die ohnehin überschrieben werden.
  • Plugin-Registry und Darstellung: Veröffentlichte Plugins aus der Registry lassen sich jetzt auch dann problemlos installieren, wenn parallel bereits eine neuere Version desselben Pakets auf ihre Freigabeprüfung wartet (#4557). Zudem zeigt die Übersicht per Code eingebundene Plugins nun mit ihrem lesbaren Namen statt ihrer technischen ID an (#2817).

Update auf EmDash 1.5: Worauf Websites mit Sandbox-Plugins achten müssen

Für die allermeisten Websites läuft das Update auf EmDash 1.5 genauso unkompliziert ab wie gewohnt. Eine wichtige Ausnahme gibt es jedoch: Wer isolierte Sandbox-Plugins (`sandboxed: []`) betreibt, muss vor dem Update sämtliche Schreibzugriffe auf die Datenbank stoppen und die Datenbank-Migration kontrolliert vorab ausführen.

Hintergrund ist die Migration 092_plugin_kv_options (#4277). EmDash unterscheidet zwischen normalen Plugins, die direkt im Hauptprozess laufen (plugins: []), und streng abgeschotteten Sandbox-Plugins (sandboxed: []). Bisher nutzten beide Modi getrennte Tabellen für ihren Schlüssel-Wert-Speicher (ctx.kv). Verschob man ein Plugin später in die Sandbox oder aus ihr heraus, waren seine gespeicherten Einstellungen plötzlich weg. Die neue Migration legt beide KV-Speicher deshalb sinnvoll zusammen – kopiert dafür aber Daten zwischen zwei Bereichen und braucht währenddessen Ruhe auf der Datenbank. (Was die Sandbox im Detail abschirmt und was nicht, habe ich in Das Plugin-Problem genauer untersucht.)

Warum man mit Sandbox-Plugins nicht einfach im laufenden Betrieb deployen sollte: Verlässt man sich auf die automatische Migration beim Serverstart, fährt EmDash unmittelbar danach alle Plugins hoch – es bleibt also keine Sekunde Zeit, das Migrationsprotokoll auf mögliche Schlüssel-Konflikte zu prüfen, bevor Plugins bereits wieder neue Daten schreiben. Ausserdem erzwingt das System nicht automatisch, dass emdash und ein separat betriebener Sandbox-Runner zeitgleich aktualisiert werden; darauf muss man selbst achten.

Ich habe dieses Szenario vorab an einer Kopie meiner Demo-Website samt aktivem Sandbox-Plugin getestet und absichtlich einen Konflikt provoziert: derselbe Schlüssel mit unterschiedlichen Werten in beiden Speichern. Beim Start protokollierte EmDash sauber die Warnung Conflicting KV values; keeping the in-process value inklusive Plugin-Name und Schlüssel. Der Wert des regulären Plugins erhielt Vorrang, alle konfliktfreien Einträge wurden übernommen, und die ursprünglichen Sandbox-Zeilen blieben unangetastet als Sicherung in _plugin_storage erhalten. Daten gehen also nicht verloren – doch im Konfliktfall liest das Sandbox-Plugin nach dem Update plötzlich einen anderen Wert als zuvor. Genau deshalb sollte man etwaige Warnungen prüfen, bevor der Schreibbetrieb weitergeht.

Websites ohne Sandbox-Plugins sind davon nicht betroffen. Da die Migration ausschliesslich Einträge aus dem KV-Speicher der Sandbox überträgt, hat sie auf Projekten ohne Sandbox-Einsatz schlicht nichts zu tun. In der Datenbank unseres Blogs The Weekly Dash, das komplett ohne Sandbox-Plugins läuft, existiert keine einzige solche Zeile.

Auch alle fünf weiteren Migrationen in 1.5 sind unkritisch und laufen vollautomatisch durch:

  • 093_menu_item_orphans hebt verwaiste Untermenüpunkte, deren übergeordneter Eintrag gelöscht wurde, offiziell auf die oberste Menüebene – dort wurden sie im Frontend ohnehin schon angezeigt, fehlten aber bisher im Admin.
  • 094_media_usage_file_url_reindex erweitert die Medienerkennung, sodass auch Bilder erfasst werden, die im Text lediglich über ihre direkte Datei-URL eingebunden sind.
  • 095_plugin_storage_unique_scope begrenzt eindeutige Indizes im Plugin-Speicher auf die jeweilige Sammlung.
  • 096_revision_kind_and_editors ergänzt die Revisionstabelle um die Art der Speicherung sowie die Liste aller Mitwirkenden.
  • 097_room_storage richtet die Tabellen für das gemeinsame Bearbeiten ein. (Die letzten beiden Migrationen werden auch dann angelegt, wenn coEditing ausgeschaltet bleibt.)

Dass die Release Notes bei der KV-Migration so deutlich warnen, rechne ich dem Team hoch an. Ein Changelog, das eine heikle Datenmigration in einem harmlosen Nebensatz versteckt, richtet mehr Schaden an als gar keins.

Schritt-für-Schritt-Anleitung: Sicher auf EmDash 1.5 aktualisieren

Die Grundlagen eines Updates habe ich bereits in EmDash aktualisieren beschrieben. Für den Sprung auf Version 1.5 empfehle ich diesen Ablauf:

  1. Datenbank sichern. Ab 1.5 läuft der Backup-Download auf Cloudflare D1 auch bei grossen Datenbeständen über 50 MB wieder zuverlässig durch.
  2. Schreibzugriffe pausieren (nur bei Einsatz von Sandbox-Plugins): Laufende Instanzen, Cronjobs und Hintergrund-Jobs von Plugins vorübergehend anhalten.
  3. `emdash` und `@emdash-cms/cloudflare` gemeinsam auf 1.5.0 anheben. Der Cloudflare-Adapter setzt ab sofort exakt dieselbe Versionsnummer voraus (#4582): npm bricht bei Abweichungen hart mit ERESOLVE ab, pnpm gibt eine Warnung aus. Diese Strenge ist Absicht, weil sich der Adapter sonst im Hintergrund still eine zweite Kopie von emdash installierte. Wer @cloudflare/kumo direkt im Projekt eingebunden hat, aktualisiert das Paket auf exakt 2.15.0 (#4308); gleiches gilt für die offiziellen Pakete Forms, Field Kit, AI Moderation und AI Search.
  4. Projekt lokal bauen (`build`) und Typen prüfen. Stoppt der Build wegen fehlerhafter Optionen in der astro.config.mjs, zuerst die gemeldeten Einträge korrigieren. Danach einmal astro check ausführen, da ungültige Props an <PortableText> nun als Typfehler auffallen.
  5. Bei Sandbox-Plugins: `pnpm emdash migrate` gezielt gegen die Produktionsdatenbank ausführen. Achtung: Der CLI-Befehl liest weder .env, .env.local noch .dev.vars automatisch ein – die Datenbank-Zugangsdaten müssen direkt als Umgebungsvariablen in der Shell exportiert sein. Anschliessend die Ausgabe auf KV-Konflikte prüfen, bevor Plugins wieder schreiben dürfen. Wie sich Werte bei Bedarf zurückrollen lassen, steht in der Upgrade-Anleitung für Plugins.
  6. Website deployen. Wer das neue Co-Editing nutzen möchte, aktiviert coEditing: true sowie das Cloudflare-Binding EMDASH_ROOMS am besten erst in einem sauberen zweiten Deployment, nachdem das Basis-Update läuft.
  7. Den neuen Admin einmal auf dem Smartphone öffnen. Nicht zur Fehlersuche, sondern weil die Bedienung dort zum ersten Mal wirklich Spass macht.

An meiner eigenen Testkopie lief das Update reibungslos durch: Nach dem Versionssprung auf 1.5.0 baute das Projekt ohne Konfigurationsfehler, alle sechs Migrationen von 092 bis 097 liefen beim ersten Start sauber durch, und mein künstlich angelegter KV-Konflikt wurde exakt wie dokumentiert gemeldet. Der einzige kleine Stolperstein war mein eigener Paketmanager: Wegen einer gesetzten Sicherheitsregel (minimumReleaseAge) blockiert mein pnpm standardmässig Pakete, die jünger als 24 Stunden sind – was einen Tag nach dem Release noch einige Astro-Abhängigkeiten betraf. Wer dieselbe Sperre nutzt, wartet entweder einen Tag ab oder definiert für EmDash und Astro eine Ausnahme. Gut zu wissen für die lokale Entwicklung: Gegen eine lokale D1-Datenbank funktioniert emdash migrate nicht ohne verbundenes Cloudflare-Konto; lokal erledigt ein kurzes astro dev die Migrationen automatisch.

Kurz gefragt: Häufige Fragen zu EmDash 1.5

Ändert EmDash 1.5 meine bestehenden Inhalte?

Nein. Alle gespeicherten Beiträge, API-Endpunkte und die Darstellung im Frontend bleiben unverändert. Die Datenbank-Migrationen betreffen ausschliesslich den Plugin-Speicher, verwaiste Menüpunkte, den Medien-Index, die Metadaten der Revisionen sowie neue Tabellen für Co-Editing. Einzige inhaltliche Ausnahme sind früher aus WordPress importierte, passwortgeschützte Beiträge – diese sollte man wie oben beschrieben manuell auf Entwurf zurückstellen.

Muss ich das Echtzeit-Co-Editing einschalten?

Nein. Ohne coEditing: true in der Konfiguration bleibt alles beim gewohnten Verhalten mit klassischer Bearbeitungssperre. Auf Cloudflare erfordert Co-Editing zusätzlich das Durable Object EmDashRoom in der wrangler.jsonc sowie im Worker-Export.

Brauche ich für den E-Mail-Versand in EmDash noch ein Plugin?

Nein. Ein normaler SMTP-Zugang genügt jetzt vollkommen und lässt sich direkt unter Einstellungen → E-Mail hinterlegen. Bisherige E-Mail-Plugins können entfernt werden.

Verschwindet meine bestehende Website durch den Staging-Modus aus Google?

Nein. Der automatische Staging-Modus greift ausschliesslich bei Websites, die nach dem Update komplett neu über das Setup eingerichtet werden. Jede bereits bestehende Live-Website bleibt unverändert für Suchmaschinen sichtbar.

Muss ich für Cloudflare-D1-Backups über 50 MB etwas einstellen?

Nein. Das Update auf EmDash 1.5 reicht aus. Das seitenweise Auslesen der Tabellen ist ohne zusätzlichen Schalter sofort aktiv.

Wer muss beim Update auf EmDash 1.5 besonders aufpassen?

Projekte, die isolierte Sandbox-Plugins einsetzen (wegen der KV-Speicher-Migration), sowie Websites, die in früheren Versionen Inhalte aus WordPress importiert haben (wegen ehemals passwortgeschützter Beiträge). Für alle anderen ist 1.5 ein reguläres Update: Pakete anheben, bauen, deployen.

Mein Fazit zu EmDash 1.5

Für mich stechen drei Neuerungen klar heraus: das gemeinsame Bearbeiten in Echtzeit, der deutlich aufgeräumtere Block-Editor und der direkte E-Mail-Versand per SMTP ohne Zusatz-Plugin. Dass Co-Editing vorerst bewusst eingeschaltet werden muss, halte ich für genau die richtige Entscheidung: Es ist der grösste Eingriff am Editor seit dem Start von EmDash, und wer die Funktion im Team braucht, aktiviert sie gezielt. Genauso wichtig sind die vielen Verbesserungen im Detail: manuell gespeicherte Versionen, die der Autosave nicht mehr überschreibt, endlich erreichbare Tabellenmenüs auf dem Smartphone, funktionierende Weiterleitungen bei Umlauten und verlässliche D1-Backups trotz neuem Cloudflare-Limit. Wer Sandbox-Plugins betreibt, plant für die Migration ein kurzes Wartungsfenster ein; wer früher aus WordPress umgezogen ist, kontrolliert einmal seine passwortgeschützten Einträge.

Wer auf dem Smartphone, bei Sonderzeichen in URLs oder rund um Cloudflare D1 noch einen Fehler findet: Issue auf GitHub aufmachen.