Le 28 septembre 2026, la version 1.0 d'EmDash a été officiellement lancée.
EmDash est un CMS open source basé sur Astro développé par Cloudflare, intégré directement dans le site Astro avec écran d'administration, et fonctionne sur Cloudflare Workers + D1 + R2.
On peut dire que c'est grosso modo la version Astro de WordPress.
Le blog interne « Yuru Log » que nous avons migré depuis microCMS dans un article précédent s'est arrêté à la version 0.22 déployée en juin, nous avons donc saisi cette occasion pour le mettre à jour directement jusqu'à la dernière version 1.2.0.
Les points forts de la version 1.0 sont la stabilité et la sécurité de la mise à niveau, les plug-ins s'exécutant dans un sandbox, et le serveur MCP pour les agents.
En conclusion, la migration a pris un jour, mais il y avait de nombreux pièges.
Si vous commencez à l'idée que « la version 1.0 devrait être stable », vous vous retrouverez bloqué non pas par EmDash lui-même, mais par les dépendances périphériques.
Contexte : 0.22 → 1.2 devait être mis à jour manuellement
La version 1.2 inclut upgrade-emdash, un CLI officiel de mise à niveau.
Il met à jour les dépendances et génère un fichier UPGRADE.md spécifique au site, mais il ne supporte que les versions 0.35 et ultérieures, donc il ne pouvait pas être utilisé à partir de 0.22.
Entre la version 0.22 et 1.2, il y a 47 migrations de base de données, dont plusieurs modifications destructrices.
Ce n'était pas quelque chose qu'on pouvait résoudre avec un simple npm install emdash@latest.
1. Faire une sauvegarde et dupliquer la base de données de production en local
npx wrangler d1 export <database-name> --remote --output=backups/pre-1.2.sql
Nous importons ensuite cela dans le D1 local et testons la migration avec les mêmes données que la production.
2. Mettre à jour les dépendances
Package | Avant la migration | Après la migration |
|---|---|---|
emdash / @emdash-cms/cloudflare / @emdash-cms/admin | 0.22.0 | 1.2.0 |
@emdash-cms/plugin-forms | 0.1.1 | 0.2.9 |
astro | 6.1.2 | 6.4.8 |
wrangler | 4.80 | 4.148 |
wrangler a dû être mis à jour en raison de la peer requirement d'emdash 1.2 (4.99 ou supérieur), et nous avons supprimé la solution temporaire de l'ère 0.22 à ce moment. @astrojs/cloudflare répondait aux peer requirements, nous l'avons donc conservé à la version 13.1.6 à ce stade. Cela s'avérera être la cause du piège suivant.
- patch-package pour la route OAuth: appliqué pour contourner un bug dans la version 0.22. Corrigé dans le corps principal.
- Injection CSS du panneau d'administration: l'admin 0.22 était conçu pour la bibliothèque UI kumo 2.4, mais le fichier de verrouillage tirait kumo 2.6, ce qui rendait les boutons de connexion et de publication invisibles (texte blanc sur fond transparent). C'est corrigé dans la version 1.2.
3. Dev ne démarre pas (piège: décalage de version de miniflare)
La raison pour laquelle le démarrage échoue après avoir mis à jour les dépendances et exécuté npm run dev était un décalage de version de miniflare.
wrangler 4.148 utilise miniflare 5 et met à jour la table _cf_ALARM (sous .wrangler/state/v3/) à 3 colonnes pour l'état local de D1.
En revanche, miniflare 4 fourni avec @astrojs/cloudflare 13.1.6 ne peut pas lire l'état local en raison d'une incompatibilité du nombre de colonnes.
La solution est de mettre à jour également @astrojs/cloudflare pour aligner la version de miniflare avec wrangler. Il suffit de se souvenir que « les versions de miniflare de wrangler et de l'adaptateur doivent être alignées » et ce sera facile la prochaine fois.
Parallèlement, la commande emdash dev présente dans la version 0.22 a été abandonnée. Le script dev a donc été restauré vers astro dev. La migration et la génération de types s'exécutent au démarrage d'astro dev.
4. Le menu de staging a disparu (piège : menus dans seed.json)
Après le démarrage de dev, les 90 migrations ont réussi et ont été poussées vers staging. À l'ouverture du panneau d'administration, la navigation globale en japonais était vide.
Le problème provient de seed/seed.json, spécifiquement de menus et de widgetAreas.
Le traitement de seed d'EmDash supprime tous les éléments avant de recréer vides s'il existe un menu ou une zone de widget du même nom.
Le fichier seed.json contenait en tant que modèle une définition de menu avec "items": [], ce qui provoquait l'initialisation du menu à chaque exécution du seed.
La solution a été de supprimer intégralement les clés menus et widgetAreas.
Le contenu des menus est géré via le panneau d'administration, il n'y a donc aucune raison de le stocker dans le seed.
5. Les liens des articles en anglais deviennent /en/posts/en/slug (piège : préfixe de locale dans entry.id)
Ceci est un changement de spécification dans la version 1.2.
Sur les sites multilingues, getEmDashCollection() renvoie maintenant un entry.id avec un préfixe de locale. Pour un article en anglais, c'est en/my-post.
Yuru Log construisait les URL des articles à partir d'entry.id, ce qui a doublé les liens des articles en anglais en /en/posts/en/my-post.
Tous les endroits où l'URL était construite — listes, sélections, résultats de recherche, RSS et canonical — ont été remplacés par entry.data.slug. Comme le type d'entry.data.slug est string | null, les types côté réception doivent également être ajustés.
Il est utile de retenir que entry.id est la clé, entry.data.slug est l'URL, et entry.data.id est l'ULID pour la base de données (pour les appels d'API).
6. Des erreurs surviennent chaque minute (piège : Cron Trigger et entrée Worker)
Dans la version 1.x, le gestionnaire scheduled() du Worker pilote la publication des articles programmés et l'exécution périodique des plugins.
Comme Cloudflare n'a pas de minuteur interne, sans Cron Trigger, les articles programmés ne seront pas publiés à l'heure prévue. Pour cette raison,
j'ai ajouté un Cron Trigger à wrangler.jsonc.
"triggers": { "crons": ["* * * * *"] }Ensuite, le message "Handler does not export a scheduled() function" s'affiche toutes les minutes.
C'est parce que le point d'entrée du Worker n'exporte pas scheduled().
La solution consiste à remplacer src/worker.ts par le point d'entrée officiel.
export { default, PluginBridge } from "@emdash-cms/cloudflare/worker";Maintenant, en plus de fetch et scheduled, nous avons aussi PluginBridge pour les plugins de type bac à sable.
Après l'avoir essayé
Points positifs après la mise à jour vers la version 1.2.
- L'éditeur a été entièrement refondu et est plus convivial. Le menu slash est maintenant groupé et la barre d'outils est désormais flottante. Cela fonctionne aussi sur mobile.
- Le bloc vidéo est désormais inclus par défaut. J'utilisais un plugin personnalisé pour l'intégration de vidéos, et je prévois de le remplacer à terme.
- Tous les contournements temporaires de l'époque 0.22 ont pu être supprimés. Plus besoin de patch-package ni d'injections CSS.
Points d'attention.
- De la version 1.0 à 1.2 en 10 jours, le rythme est soutenu. Pour un certain temps, il semble nécessaire de vérifier chaque version mineure en staging.
Conclusion
- La migration de 0.22 vers 1.2 est manuelle.
Le CLI upgrade-emdashne cible que les versions 0.35 et ultérieures. - Alignez les générations de wrangler et de miniflare de l'adaptateur → si elles ne sont pas alignées, le démarrage en dev échoue
- Dans seed.json, ne laissez pas de modèles vides pour
menus/widgetAreas→ ils disparaissent à chaque seed - Sur les sites multilingues,
entry.idest préfixé par la locale → l'URL provient deentry.data.slug - Si vous ajoutez un Cron Trigger, le point d'entrée Worker doit être
@emdash-cms/cloudflare/worker
Bien que chacune de ces corrections ne prenne que quelques lignes une fois bien comprise, progresser en enquêtant sur chacune consomme beaucoup plus de temps qu'on ne l'imagine.
Cela dit, le fait que tous les correctifs et contournements CSS appliqués à la version 0.22 aient pu être supprimés est la preuve que les petits bugs ont été corrigés en amont de la version finale.
Il y a six mois, c'était plutôt une approche « expérimentale, testons un remplacement », mais après la version 1.0, en tenant compte de l'effort de suivi des mises à jour, EmDash est maintenant un CMS que je pense être une option sérieuse à considérer pour une utilisation réelle.
Passé du DTP au monde du web, il s'est avéré être un « sage des techniques » maîtrisant le markup, le frontend, la direction et l'accessibilité. Actif depuis la fondation de Liberogic, il est devenu une référence incontournable en interne. Récemment, il explore l'optimisation via des prompts IA, se demandant « Pourrions-nous déléguer davantage la conformité en accessibilité à l'IA ? ». Sa technologie et sa réflexion continuent d'évoluer.
Ayumu Futamata
Spécialiste en accessibilité web certifié par l'IAAP (WAS) / Ingénieur markup / Ingénieur frontend / Directeur web