[{"data":1,"prerenderedAt":819},["ShallowReactive",2],{"i-ic:outline-arrow-upward":3,"Footer_afPiwGMwNiEyV4syWzw87ovzxHAgs4iwKtCn4zqBf8E":8,"\u002Farticles\u002Femdash-cms-pour-agent":16,"i-material-symbols:home":792,"i-material-symbols:search":794,"i-material-symbols:ios-share":796,"Brand_bAcjTzQpW6OVpFK319jfMki97vH1GrZiqHmeI7Xg4o":798,"ArticleDetails_ksHvE8FNKjVxThBAbkthWm7wZXcJFWJ1wBHcbZUHd9w":803,"AppImg_IyX8AyXnvzxMhkQHFSbpXBHOtGi2gizwCEtOpbCcVEk":814},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"m4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8z\"\u002F>",["Island",9],{"key":10,"result":11},"Footer_afPiwGMwNiEyV4syWzw87ovzxHAgs4iwKtCn4zqBf8E",{"head":12},{"style":13},[14],{"innerHTML":15},":where(.i-mdi\\:github){display:inline-block;width:1em;height:1em;background-color:currentColor;-webkit-mask-image:var(--svg);mask-image:var(--svg);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;--svg:url(\"data:image\u002Fsvg+xml,%3Csvg xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='black' d='M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2'\u002F%3E%3C\u002Fsvg%3E\")}",{"id":17,"title":18,"author":19,"body":22,"description":784,"extension":785,"meta":786,"navigation":443,"path":787,"publicationDate":788,"seo":789,"stem":790,"__hash__":791},"articles\u002Farticles\u002Femdash-cms-pour-agent.md","EmDash CMS 1.0 : pas un nouveau WordPress, mais un vrai bon CMS",{"name":20,"url":21},"@patrickfaramaz ","https:\u002F\u002Ftwitter.com\u002Fpatrickfaramaz",{"type":23,"value":24,"toc":767},"minimark",[25,29,34,37,40,43,47,59,70,73,77,87,90,94,102,109,228,239,242,245,249,252,255,259,266,404,407,411,422,483,501,505,512,515,519,522,525,528,540,544,547,550,553,557,564,575,622,629,632,636,643,646,650,653,697,701,704,707,711,763],[26,27,28],"p",{},"EmDash CMS est passé en 1.0 le 28 septembre. Je l'ai pris en main, loin de la hype ou des vidéos rapidement enregistrées pour faire des vues, voici ce que j'en retiens.",[30,31,33],"h2",{"id":32},"une-communication-de-lancement-maladroite","Une communication de lancement maladroite",[26,35,36],{},"Rappel du contexte : Cloudflare a annoncé EmDash le 1er avril 2026 avec un titre qui ne laissait pas de place au doute : « le successeur spirituel de WordPress ». Un 1er avril, beaucoup ont cru à une blague, ce que l'équipe reconnaît elle-même.",[26,38,39],{},"Le problème, c'était surtout la comparaison. Sur Hacker News, beaucoup ont répondu que WordPress n'a pas gagné grâce à la qualité de son code, mais parce que n'importe qui peut créer et éditer son site. Matt Mullenweg (le créateur de WordPress) a répondu dans un billet que l'esprit de WordPress, c'est de tourner partout.",[26,41,42],{},"Six mois plus tard, le discours a changé. La page d'accueil parle maintenant d'« un CMS open source pour Astro, pensé pour les humains et les agents », et l'annonce de la 1.0 le présente comme « le meilleur CMS pour les agents IA ». Et franchement, c'est mieux comme ça.",[30,44,46],{"id":45},"la-base-taxonomies-menus-widgets-seo","La base : taxonomies, menus, widgets, SEO",[26,48,49,50,54,55,58],{},"Si vous venez de WordPress, vous ne serez pas perdu. Il y a des taxonomies : ",[51,52,53],"code",{},"category"," (hiérarchique) et ",[51,56,57],{},"tag"," (à plat) sont fournies d'office, et vous pouvez créer les vôtres. Les menus se gèrent dans l'admin (contenus, liens libres, sous-menus). Les zones de widgets fonctionnent comme on s'y attend : une zone nommée dans le template, et l'éditeur choisit ce qu'il y met par glisser-déposer.",[26,60,61,62,65,66,69],{},"Le SEO est intégré, et c'est un vrai plus. On l'active collection par collection : on a alors un panneau par contenu (titre, description, image, canonical, noindex), les balises Open Graph via ",[51,63,64],{},"\u003CEmDashHead>",", du JSON-LD, les sitemaps, le ",[51,67,68],{},"robots.txt"," et même les redirections avec un journal des 404. Pas besoin d'un plugin.",[26,71,72],{},"Particularité : l'admin ne gère que les données. Un menu ou un widget n'apparaît sur le site que si un composant Astro le récupère et l'affiche.",[30,74,76],{"id":75},"comme-wordpress-vraiment","Comme WordPress, vraiment ?",[26,78,79,80,83,84,86],{},"Seul souci, c'est que oui, il ressemble à WordPress, mais au WordPress d'il y a 5 ans !",[81,82],"br",{},"\nDepuis l'arrivée de Gutenberg et du mode *Full Site Editing*, le CMS est passé sur une autre dimension en termes de gestion de contenu. En tant que développeur de sites WordPress, je peux dire sans rougir que l'éditeur Gutenberg est actuellement le meilleur système existant dans un CMS.",[81,85],{},"\nLes widgets ? Ils sont quasi plus utilisés sur les sites modernes.",[26,88,89],{},"Alors oui, emDash corrige certains des défauts de WordPress, comme le SEO et le multilingue natif, mais certaines fonctionnalités ne sont pas disponibles. Il est impossible de modifier la navigation admin, par exemple. Nous y reviendrons plus bas.",[30,91,93],{"id":92},"le-contenu-du-portable-text-en-base","Le contenu : du Portable Text en base",[26,95,96,97,101],{},"Le contenu riche est stocké en base sous forme de JSON, au format ",[98,99,100],"strong",{},"Portable Text",". Portable Text est un format JSON créé par Sanity.",[26,103,104,105,108],{},"Un champ ",[51,106,107],{},"portableText"," contient un tableau JSON de blocs. C'est une spécification ouverte : pas de HTML sérialisé à parser, et un contenu réutilisable ailleurs.",[110,111,116],"pre",{"className":112,"code":113,"language":114,"meta":115,"style":115},"language-js shiki shiki-themes synthwave-84","[\n  {\n    \"_type\": \"block\",\n    \"style\": \"normal\",\n    \"children\": [\n      {\n        \"_type\": \"span\",\n        \"text\": \"Double Slash Podcast\"\n      }\n    ]\n  }\n]\n","js","",[51,117,118,127,133,150,163,174,180,193,204,210,216,222],{"__ignoreMap":115},[119,120,123],"span",{"class":121,"line":122},"line",1,[119,124,126],{"class":125},"soy-K","[\n",[119,128,130],{"class":121,"line":129},2,[119,131,132],{"class":125},"  {\n",[119,134,136,140,144,147],{"class":121,"line":135},3,[119,137,139],{"class":138},"sFl1-","    \"_type\"",[119,141,143],{"class":142},"s2hdG",":",[119,145,146],{"class":138}," \"block\"",[119,148,149],{"class":125},",\n",[119,151,153,156,158,161],{"class":121,"line":152},4,[119,154,155],{"class":138},"    \"style\"",[119,157,143],{"class":142},[119,159,160],{"class":138}," \"normal\"",[119,162,149],{"class":125},[119,164,166,169,171],{"class":121,"line":165},5,[119,167,168],{"class":138},"    \"children\"",[119,170,143],{"class":142},[119,172,173],{"class":125}," [\n",[119,175,177],{"class":121,"line":176},6,[119,178,179],{"class":125},"      {\n",[119,181,183,186,188,191],{"class":121,"line":182},7,[119,184,185],{"class":138},"        \"_type\"",[119,187,143],{"class":142},[119,189,190],{"class":138}," \"span\"",[119,192,149],{"class":125},[119,194,196,199,201],{"class":121,"line":195},8,[119,197,198],{"class":138},"        \"text\"",[119,200,143],{"class":142},[119,202,203],{"class":138}," \"Double Slash Podcast\"\n",[119,205,207],{"class":121,"line":206},9,[119,208,209],{"class":125},"      }\n",[119,211,213],{"class":121,"line":212},10,[119,214,215],{"class":125},"    ]\n",[119,217,219],{"class":121,"line":218},11,[119,220,221],{"class":125},"  }\n",[119,223,225],{"class":121,"line":224},12,[119,226,227],{"class":125},"]\n",[26,229,230,231,234,235,238],{},"L'éditeur (TipTap) fonctionne par blocs : titres, listes, images, galeries, vidéos, code, tableaux, HTML, sections réutilisables, et on insère un bloc avec ",[51,232,233],{},"\u002F",". On peut créer ses propres blocs : via un plugin (que l'on créer) qui déclare le bloc (ses champs passent par le Block Kit) et fournit un composant Astro pour le rendu. Il existe aussi un champ ",[51,236,237],{},"blocks"," pour composer une page à partir de types de blocs définis dans le seed.",[26,240,241],{},"Par contre, pour le moment, un bloc custom ne s'édite pas dans le mode \"live edit\". On remplit un formulaire dans une boîte de dialogue, et le rendu final n'existe que côté Astro.",[26,243,244],{},"À noter que chaque collection a sa propre table au lieu de tout mélanger dans une seule table comme c'est le cas sur WordPress.",[30,246,248],{"id":247},"les-content-types-et-les-champs-flexibles","Les content types et les champs flexibles.",[26,250,251],{},"On peut créer autant de content type que l'on veut. Équivalent aux fameux CPT de WordPress. Avec différentes options : routable, SEO, versioning, on active ou pas ce que l'on veut.\nComme mentionné juste avant, une table est créée pour une nouvelle collection. C'est propre.",[26,253,254],{},"Et dans ces content types, on peut modéliser les champs dont on a besoin. On a les champs par défaut : ID, slug, statut, etc. Et à nous de définir si l'on veut un champ pour telle valeur, etc. 17 types de champs pour le moment : texte court, texte long, nombre, JSON, liste déroulante, répéteur (9 champs possibles). Ici, pas besoin d'ACF ou de coder. C'est natif et très pratique.",[30,256,258],{"id":257},"le-multilingue-natif","Le multilingue, natif",[26,260,261,262,265],{},"Le multilingue est intégré, et il s'appuie directement sur l'i18n d'Astro. Par défaut, il est désactivé. Pour l'activer, on ajoute un bloc ",[51,263,264],{},"i18n"," dans la config Astro, et EmDash y lit la liste des langues, la langue par défaut et les fallbacks :",[110,267,269],{"className":112,"code":268,"language":114,"meta":115,"style":115},"\u002F\u002F astro.config.mjs\nexport default defineConfig({\n  i18n: {\n    defaultLocale: \"en\",\n    locales: [\"en\", \"fr\", \"es\"],\n    fallback: { fr: \"en\", es: \"en\" },\n  },\n  integrations: [emdash({ \u002F* database, storage… *\u002F })],\n});\n",[51,270,271,277,294,305,317,344,373,378,399],{"__ignoreMap":115},[119,272,273],{"class":121,"line":122},[119,274,276],{"class":275},"sjThu","\u002F\u002F astro.config.mjs\n",[119,278,279,283,287,291],{"class":121,"line":129},[119,280,282],{"class":281},"sfE7D","export",[119,284,286],{"class":285},"scrqX"," default",[119,288,290],{"class":289},"sgRlq"," defineConfig",[119,292,293],{"class":125},"({\n",[119,295,296,300,302],{"class":121,"line":135},[119,297,299],{"class":298},"sqjNi","  i18n",[119,301,143],{"class":142},[119,303,304],{"class":125}," {\n",[119,306,307,310,312,315],{"class":121,"line":152},[119,308,309],{"class":298},"    defaultLocale",[119,311,143],{"class":142},[119,313,314],{"class":138}," \"en\"",[119,316,149],{"class":125},[119,318,319,322,324,327,330,333,336,338,341],{"class":121,"line":165},[119,320,321],{"class":298},"    locales",[119,323,143],{"class":142},[119,325,326],{"class":125}," [",[119,328,329],{"class":138},"\"en\"",[119,331,332],{"class":125},", ",[119,334,335],{"class":138},"\"fr\"",[119,337,332],{"class":125},[119,339,340],{"class":138},"\"es\"",[119,342,343],{"class":125},"],\n",[119,345,346,349,351,354,357,359,361,363,366,368,370],{"class":121,"line":176},[119,347,348],{"class":298},"    fallback",[119,350,143],{"class":142},[119,352,353],{"class":125}," { ",[119,355,356],{"class":298},"fr",[119,358,143],{"class":142},[119,360,314],{"class":138},[119,362,332],{"class":125},[119,364,365],{"class":298},"es",[119,367,143],{"class":142},[119,369,314],{"class":138},[119,371,372],{"class":125}," },\n",[119,374,375],{"class":121,"line":182},[119,376,377],{"class":125},"  },\n",[119,379,380,383,385,387,390,393,396],{"class":121,"line":195},[119,381,382],{"class":298},"  integrations",[119,384,143],{"class":142},[119,386,326],{"class":125},[119,388,389],{"class":289},"emdash",[119,391,392],{"class":125},"({ ",[119,394,395],{"class":275},"\u002F* database, storage… *\u002F",[119,397,398],{"class":125}," })],\n",[119,400,401],{"class":121,"line":206},[119,402,403],{"class":125},"});\n",[26,405,406],{},"Chaque traduction est une entrée à part entière, avec son slug, son statut et son historique. On peut donc publier l'anglais et garder le français en brouillon. Dans l'éditeur, un panneau « Translations » permet de créer chaque version.",[30,408,410],{"id":409},"le-front-avec-astro","Le front avec Astro",[26,412,413,414,417,418,421],{},"Côté front, pas de surprise : c'est du Astro. EmDash est une intégration Astro, et votre thème est un projet Astro classique avec des pages, des layouts et des composants. EmDash fournit surtout des helpers pour récupérer les contenus : ",[51,415,416],{},"getEmDashCollection()"," pour une liste, ",[51,419,420],{},"getEmDashEntry()"," pour une entrée.",[110,423,427],{"className":424,"code":425,"language":426,"meta":115,"style":115},"language-astro shiki shiki-themes synthwave-84","---\nimport { getEmDashCollection } from \"emdash\";\n\nconst { entries: posts } = await getEmDashCollection(\"posts\", {\n  orderBy: { published_at: \"desc\" },\n  limit: 7,\n});\n---\n\u003Cul>\n  {posts.map((post) => \u003Cli>\u003Ca href={`\u002Fposts\u002F${post.id}`}>{post.data.title}\u003C\u002Fa>\u003C\u002Fli>)}\n\u003C\u002Ful>\n","astro",[51,428,429,434,439,445,450,455,460,464,468,473,478],{"__ignoreMap":115},[119,430,431],{"class":121,"line":122},[119,432,433],{},"---\n",[119,435,436],{"class":121,"line":129},[119,437,438],{},"import { getEmDashCollection } from \"emdash\";\n",[119,440,441],{"class":121,"line":135},[119,442,444],{"emptyLinePlaceholder":443},true,"\n",[119,446,447],{"class":121,"line":152},[119,448,449],{},"const { entries: posts } = await getEmDashCollection(\"posts\", {\n",[119,451,452],{"class":121,"line":165},[119,453,454],{},"  orderBy: { published_at: \"desc\" },\n",[119,456,457],{"class":121,"line":176},[119,458,459],{},"  limit: 7,\n",[119,461,462],{"class":121,"line":182},[119,463,403],{},[119,465,466],{"class":121,"line":195},[119,467,433],{},[119,469,470],{"class":121,"line":206},[119,471,472],{},"\u003Cul>\n",[119,474,475],{"class":121,"line":212},[119,476,477],{},"  {posts.map((post) => \u003Cli>\u003Ca href={`\u002Fposts\u002F${post.id}`}>{post.data.title}\u003C\u002Fa>\u003C\u002Fli>)}\n",[119,479,480],{"class":121,"line":218},[119,481,482],{},"\u003C\u002Ful>\n",[26,484,485,486,489,490,493,494,332,497,500],{},"Pour le reste, il y a des composants dans ",[51,487,488],{},"emdash\u002Fui"," comme ",[51,491,492],{},"\u003CPortableText>"," ou ",[51,495,496],{},"\u003CImage>",[51,498,499],{},"getMenu()"," pour les menus, et des types TypeScript générés à partir de votre modèle de contenu.",[30,502,504],{"id":503},"lauthentification-de-ladmin","L'authentification de l'admin",[26,506,507,508,511],{},"Point fort d'EmDash, pas de mot de passe. La méthode par défaut, ce sont les ",[98,509,510],{},"passkeys"," (WebAuthn). On peut ajouter des fournisseurs de connexion : GitHub, Google et Microsoft sont inclus, Atmosphere (les comptes AT Protocol, comme Bluesky) s'installe à part, et l'interface est ouverte à d'autres fournisseurs. Il existe aussi le magic link par e-mail, à condition d'avoir configuré un fournisseur d'e-mail. Sur Cloudflare, on peut enfin confier toute l'authentification à Cloudflare Access.",[26,513,514],{},"Côté rôles, on retrouve le classique : Subscriber, Contributor, Author, Editor, Admin.",[30,516,518],{"id":517},"les-plugins","Les plugins",[26,520,521],{},"C'est ici qu'EmDash tient vraiment sa promesse de départ. Un plugin « sandboxé » tourne dans un environnement isolé. Par défaut, il n'a accès ni au contenu ni au réseau. Il déclare ce dont il a besoin dans son manifeste (lire le contenu, envoyer un e-mail, appeler un domaine précis), et l'administrateur valide ces permissions à l'installation, comme pour une app mobile. En vrai, qui va vérifier les permissions ? Pas grand monde.",[26,523,524],{},"Grosse nouveauté de la 1.0 : le sandbox fonctionne aussi sur Node.js, et plus seulement sur Cloudflare. La critique du lancement tombe donc en grande partie. La 1.0 apporte aussi un registre de plugins décentralisé, construit sur AT Protocol : les auteurs gardent la maîtrise de leurs publications. Avant la v1, le répertoire contenait 9 plugins. Au moment où j'écris ces lignes, il y en a une cinquantaine. Il ne faut pas hésiter à chercher sur GitHub pour trouver des plugins.",[26,526,527],{},"Il existe aussi des plugins « natifs », qui tournent dans le même processus que le site et ont accès à tout. Ce sont eux qui permettent les pages d'admin en React ou les composants de rendu.",[529,530,531],"ul",{},[532,533,534],"li",{},[535,536,537],"a",{"href":537,"rel":538},"https:\u002F\u002Fplugins.emdashcms.com\u002F",[539],"nofollow",[30,541,543],{"id":542},"le-déploiement","Le déploiement",[26,545,546],{},"Deux options officielles. Sur Cloudflare Workers, avec D1 pour la base et R2 pour les médias. Ou sur n'importe quel serveur Node.js, avec SQLite, PostgreSQL ou libSQL et un stockage local ou compatible S3. MySQL n'est pas pris en charge, ce qui est étonnant puisque c'est l'une des bases de données les plus répandues.",[26,548,549],{},"Les hébergements Node.js sont devenus courants, mais pas autant que les hébergements PHP\u002FMySQL. En revanche, grâce au MCP, un agent peut accéder facilement à la documentation et déployer seul sur Cloudflare.",[26,551,552],{},"Un détail à connaître : sur Cloudflare, les plugins sandboxés demandent le plan Workers Paid. Sans lui, le site fonctionne, mais sans ces plugins.",[30,554,556],{"id":555},"x402","x402 !",[26,558,559,560,563],{},"x402 est un protocole de paiement natif HTTP qui existe depuis le début du web ! Un client demande une ressource payante, le serveur répond ",[51,561,562],{},"402 Payment Required"," avec des instructions de paiement lisibles par une machine, et le client (souvent un agent) paie puis relance la requête. Le code 402 dormait dans la spec HTTP depuis des années, et voilà enfin quelqu'un qui s'en sert !",[26,565,566,567,570,571,574],{},"Avec EmDash, cela se fait via le package ",[51,568,569],{},"@emdash-cms\u002Fx402",". On configure son portefeuille et le réseau, puis on protège une page avec ",[51,572,573],{},"enforce()",". Le prix peut même venir d'un champ numérique de votre collection, donc chaque article a son tarif, réglé par l'éditeur :",[110,576,578],{"className":424,"code":577,"language":426,"meta":115,"style":115},"---\nconst { x402 } = Astro.locals;\nconst result = await x402.enforce(Astro.request, {\n  price: entry.data.price ?? \"$0.01\",\n  description: entry.data.title,\n});\nif (result instanceof Response) return result;\nx402.applyHeaders(result, Astro.response);\n---\n",[51,579,580,584,589,594,599,604,608,613,618],{"__ignoreMap":115},[119,581,582],{"class":121,"line":122},[119,583,433],{},[119,585,586],{"class":121,"line":129},[119,587,588],{},"const { x402 } = Astro.locals;\n",[119,590,591],{"class":121,"line":135},[119,592,593],{},"const result = await x402.enforce(Astro.request, {\n",[119,595,596],{"class":121,"line":152},[119,597,598],{},"  price: entry.data.price ?? \"$0.01\",\n",[119,600,601],{"class":121,"line":165},[119,602,603],{},"  description: entry.data.title,\n",[119,605,606],{"class":121,"line":176},[119,607,403],{},[119,609,610],{"class":121,"line":182},[119,611,612],{},"if (result instanceof Response) return result;\n",[119,614,615],{"class":121,"line":195},[119,616,617],{},"x402.applyHeaders(result, Astro.response);\n",[119,619,620],{"class":121,"line":206},[119,621,433],{},[26,623,624,625,628],{},"Et sur Cloudflare, il existe un mode ",[51,626,627],{},"botOnly"," : seuls les robots paient, les humains lisent gratuitement. Faire payer les crawlers IA sans mettre de paywall pour les lecteurs, je trouve l'idée géniale. Une nuance quand même : l'annonce d'avril parlait d'un x402 intégré « sans aucun travail d'ingénierie ». Dans la doc actuelle, c'est une intégration séparée, et il faut ajouter quelques lignes par route.",[26,630,631],{},"À noter que le paiement utilise la crypto et la blockchain, ce qui le limite aux personnes qui maîtrisent ces technologies.",[30,633,635],{"id":634},"lia-et-le-mcp","L'IA et le MCP",[26,637,638,639,642],{},"Chaque site EmDash embarque un serveur MCP, actif par défaut sur ",[51,640,641],{},"\u002F_emdash\u002Fapi\u002Fmcp"," et protégé par OAuth. On y branche Claude, ChatGPT,Codex ou n'importe quel agent via un token API. On leur demande en langage naturel de rédiger un brouillon, de planifier une publication, de comparer deux versions, de gérer les médias, les menus ou les taxonomies, ou de créer une traduction. Les droits dépendent à la fois des permissions accordées et du rôle de l'utilisateur.",[26,644,645],{},"Ajoutez une CLI et des Agent Skills livrées avec les templates, plus un MCP connecté à la documentation, et on comprend le nouveau positionnement.",[30,647,649],{"id":648},"les-défauts","Les défauts",[26,651,652],{},"Voici ce qui me gêne à l'usage :",[529,654,655,661,671,681,691],{},[532,656,657,660],{},[98,658,659],{},"Le menu de l'admin n'est pas modifiable."," Il se construit à partir des collections et des plugins, et je ne peux pas le réorganiser comme je veux. Les plugins peuvent ajouter leurs propres pages, mais pas remplacer un écran du core.",[532,662,663,666,667,670],{},[98,664,665],{},"On ne peut pas désactiver des fonctionnalités."," Les commentaires, par exemple. La doc indique qu'ils s'activent collection par collection, et que le serveur MCP se coupe avec ",[51,668,669],{},"mcp: false",", mais il n'existe pas de moyen général d'alléger l'admin.",[532,672,673,676,677,680],{},[98,674,675],{},"Peu de personnalisation des e-mails."," Un hook ",[51,678,679],{},"email:beforeSend"," permet de modifier les messages envoyés par les plugins, mais pas les e-mails d'authentification du système.",[532,682,683,686,687,690],{},[98,684,685],{},"Peu de personnalisation de l'admin."," On peut changer le logo, le nom et le favicon (option ",[51,688,689],{},"admin","), mais ça ne va pas beaucoup plus loin.",[532,692,693,696],{},[98,694,695],{},"Impossible de créer de nouveaux rôles",". On doit se cantonner aux rôles par défaut.",[30,698,700],{"id":699},"conclusion","Conclusion",[26,702,703],{},"Malgré ses défauts, EmDash est un bon produit. Finalement, il n'est pas vraiment comparable à WordPress : ce n'est ni le même écosystème, ni le même public. C'est un CMS pour les devs Astro, sûr par défaut, pensé pour les agents, avec des idées vraiment neuves comme x402.",[26,705,706],{},"C'est un bon CMS qui ne demande qu'à grandir. Et au rythme où il évolue (la 1.1 est déjà sortie trois jours après la 1.0), je pense qu'il va grandir vite.",[30,708,710],{"id":709},"sources","Sources",[712,713,714,721,728,735,742,749,756],"ol",{},[532,715,716],{},[535,717,720],{"href":718,"rel":719},"https:\u002F\u002Fblog.cloudflare.com\u002Femdash-wordpress\u002F",[539],"Introducing EmDash - the spiritual successor to WordPress that solves plugin security (Cloudflare Blog)",[532,722,723],{},[535,724,727],{"href":725,"rel":726},"https:\u002F\u002Fblog.cloudflare.com\u002Femdash-cms-plugin-registry\u002F",[539],"EmDash 1.0: the stable CMS with a secure plugin registry (Cloudflare Blog)",[532,729,730],{},[535,731,734],{"href":732,"rel":733},"https:\u002F\u002Femdashcms.com\u002Fblog\u002Femdash-1-0",[539],"EmDash 1.0: an open source CMS for Astro (blog EmDash)",[532,736,737],{},[535,738,741],{"href":739,"rel":740},"https:\u002F\u002Fgithub.com\u002Femdash-cms\u002Femdash\u002Fblob\u002Fmain\u002Fpackages\u002Fcore\u002FCHANGELOG.md",[539],"CHANGELOG du package emdash (GitHub)",[532,743,744],{},[535,745,748],{"href":746,"rel":747},"https:\u002F\u002Fnews.ycombinator.com\u002Fitem?id=47602832",[539],"Fil Hacker News sur l'annonce d'EmDash",[532,750,751],{},[535,752,755],{"href":753,"rel":754},"https:\u002F\u002Fma.tt\u002F2026\u002F04\u002Femdash-feedback\u002F",[539],"EmDash Feedback, Matt Mullenweg",[532,757,758],{},[535,759,762],{"href":760,"rel":761},"https:\u002F\u002Femdashcms.com\u002F",[539],"Page d'accueil EmDash CMS",[764,765,766],"style",{},"html pre.shiki code .soy-K, html code.shiki .soy-K{--shiki-default:#BBBBBB}html pre.shiki code .sFl1-, html code.shiki .sFl1-{--shiki-default:#FF8B39}html pre.shiki code .s2hdG, html code.shiki .s2hdG{--shiki-default:#B6B1B1}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sjThu, html code.shiki .sjThu{--shiki-default:#848BBD;--shiki-default-font-style:italic}html pre.shiki code .sfE7D, html code.shiki .sfE7D{--shiki-default:#72F1B8}html pre.shiki code .scrqX, html code.shiki .scrqX{--shiki-default:#FEDE5D}html pre.shiki code .sgRlq, html code.shiki .sgRlq{--shiki-default:#36F9F6}html pre.shiki code .sqjNi, html code.shiki .sqjNi{--shiki-default:#FF7EDB}",{"title":115,"searchDepth":129,"depth":129,"links":768},[769,770,771,772,773,774,775,776,777,778,779,780,781,782,783],{"id":32,"depth":129,"text":33},{"id":45,"depth":129,"text":46},{"id":75,"depth":129,"text":76},{"id":92,"depth":129,"text":93},{"id":247,"depth":129,"text":248},{"id":257,"depth":129,"text":258},{"id":409,"depth":129,"text":410},{"id":503,"depth":129,"text":504},{"id":517,"depth":129,"text":518},{"id":542,"depth":129,"text":543},{"id":555,"depth":129,"text":556},{"id":634,"depth":129,"text":635},{"id":648,"depth":129,"text":649},{"id":699,"depth":129,"text":700},{"id":709,"depth":129,"text":710},"EmDash CMS, le CMS de Cloudflare basé sur Astro, passe en 1.0. Une vraie analyse sans bullshit","md",{},"\u002Farticles\u002Femdash-cms-pour-agent","2026-10-06",{"title":18,"description":784},"articles\u002Femdash-cms-pour-agent","--GjhS3E-GDJNl3RVHOAQ5T0-wn86ZZbcZNKxR0UckI",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":793},"\u003Cpath fill=\"currentColor\" d=\"M4 21V9l8-6l8 6v12h-6v-7h-4v7z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":795},"\u003Cpath fill=\"currentColor\" d=\"m19.6 21l-6.3-6.3q-.75.6-1.725.95T9.5 16q-2.725 0-4.612-1.888T3 9.5t1.888-4.612T9.5 3t4.613 1.888T16 9.5q0 1.1-.35 2.075T14.7 13.3l6.3 6.3zM9.5 14q1.875 0 3.188-1.312T14 9.5t-1.312-3.187T9.5 5T6.313 6.313T5 9.5t1.313 3.188T9.5 14\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":797},"\u003Cpath fill=\"currentColor\" d=\"M6 22q-.825 0-1.412-.587T4 20V10q0-.825.588-1.412T6 8h3v2H6v10h12V10h-3V8h3q.825 0 1.413.588T20 10v10q0 .825-.587 1.413T18 22zm5-6V4.825l-1.6 1.6L8 5l4-4l4 4l-1.4 1.425l-1.6-1.6V16z\"\u002F>",["Island",799],{"key":800,"result":801},"Brand_bAcjTzQpW6OVpFK319jfMki97vH1GrZiqHmeI7Xg4o",{"head":802},{},["Island",804],{"key":805,"result":806},"ArticleDetails_ksHvE8FNKjVxThBAbkthWm7wZXcJFWJ1wBHcbZUHd9w",{"head":807},{"script":808},[809],{"key":810,"tagPosition":811,"tagPriority":812,"innerHTML":813},":Rq3LAwVg9E:","bodyClose","critical","document.querySelectorAll('[data-prehydrate-id*=\":Rq3LAwVg9E:\"]').forEach(e=>{let t=window._nuxtTimeNow||=Date.now(),n=(e,t)=>t>0?e[0].toUpperCase()+e.slice(1):e,r=e.getAttribute(`datetime`);if(!r)return;let i=new Date(r);if(Number.isNaN(i.getTime()))return;let a={};for(let t of e.getAttributeNames())if(t.startsWith(`data-`)){let r=t.slice(5).split(`-`).map(n).join(``);r===`relativeStyle`&&(r=`style`);let i=e.getAttribute(t);a[r]=i===`true`||i!==`false`&&i}if(a.relative){let n=(i.getTime()-t)\u002F1e3,r=[{unit:`second`,seconds:1,threshold:60},{unit:`minute`,seconds:60,threshold:60},{unit:`hour`,seconds:3600,threshold:24},{unit:`day`,seconds:86400,threshold:30},{unit:`month`,seconds:2592e3,threshold:12},{unit:`year`,seconds:31536e3,threshold:1\u002F0}],{unit:o,seconds:s}=r.find(({seconds:e,threshold:t})=>Math.abs(n\u002Fe)\u003Ct)||r[r.length-1],c=n\u002Fs;e.textContent=new Intl.RelativeTimeFormat(a.locale,a).format(Math.round(c),o)}else e.textContent=new Intl.DateTimeFormat(a.locale,a).format(i)})",["Island",815],{"key":816,"result":817},"AppImg_IyX8AyXnvzxMhkQHFSbpXBHOtGi2gizwCEtOpbCcVEk",{"head":818},{},1791301456930]