{"id":98011,"date":"2026-10-05T03:02:00","date_gmt":"2026-10-05T07:02:00","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=98011"},"modified":"2026-09-29T07:53:07","modified_gmt":"2026-09-29T11:53:07","slug":"build-emdash-plugins-with-ai-98011","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/build-emdash-plugins-with-ai-98011\/","title":{"rendered":"7 EmDash Plugins You Can Build With AI Right Now (Even If You\u2019re Not a Coder)"},"content":{"rendered":"<p><a href=\"https:\/\/blog.cloudflare.com\/emdash-cms-open-source\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">Cloudflare&#8217;s EmDash CMS<\/a> launched as version 0.1.0. The plugin marketplace sits empty. That&#8217;s not a bug\u2014it&#8217;s an opening.<\/p>\n<p>Because EmDash ships with a built-in MCP server and agent skills files, you can generate plugins using natural language. No PHP required. No WordPress hooks to memorize. The sandboxed runtime handles security for you.<\/p>\n<p>Here are seven plugins you can build today with Claude, Cursor, or any MCP-compatible coding agent. Each one solves a real WordPress pain point that EmDash doesn&#8217;t yet cover natively.<\/p>\n<h2>1. Content Blocker for Drafts That Shouldn&#8217;t Go Live<\/h2>\n<p><strong>The problem:<\/strong> You schedule a post. You forget to remove a placeholder paragraph. It publishes at 3 AM.<\/p>\n<p><strong>The plugin:<\/strong> On the <code>post:publish<\/code>codecodecodecode hook, this plugin checks the post body for a list of blocked phrases (like &#8220;TODO: add real content here&#8221; or &#8220;lorem ipsum&#8221;). If found, it reverts the post to draft and sends you an email notification.<\/p>\n<p><strong>What to tell your <a href=\"https:\/\/overcentral.com\/en\/meta-muse-ai-agent-80441\/\" title=\"Meta Launches Muse AI Agent, Needs User Trust\" data-iacss-internal=\"1\">AI agent<\/a>:<\/strong> &#8220;Create an EmDash sandbox plugin that registers a hook on <code>post:publish<\/code>codecodecodecode. When triggered, scan the post content for these three blocked phrases. If any match, set the post status back to &#8216;draft&#8217; and use the <code>email:send<\/code>codecodecodecode capability to notify the site admin.&#8221;<\/p>\n<p>The agent will generate a <code>definePlugin<\/code>codecodecodecode function with capabilities <code>read:content<\/code>codecodecodecode, <code>write:content<\/code>codecodecodecode, and <code>email:send<\/code>codecodecodecode. It&#8217;s roughly 40 lines of TypeScript.<\/p>\n<h2>2. AI-Generated Meta Descriptions<\/h2>\n<p><strong>The problem:<\/strong> Yoast SEO doesn&#8217;t exist on EmDash yet. You&#8217;re writing meta descriptions by hand.<\/p>\n<p><strong>The plugin:<\/strong> On <code>post:save<\/code>codecodecodecode, this plugin reads the post body, calls <a href=\"https:\/\/overcentral.com\/en\/ai-avatar-empire-96590\/\" title=\"Build an AI Avatar Empire Without Showing Your Face\" data-iacss-internal=\"1\">an AI<\/a> API (via a declared <code>http:post<\/code>codecodecodecode capability), and writes the returned summary into the SEO meta description field.<\/p>\n<p><strong>The catch:<\/strong> Sandboxed plugins can&#8217;t make arbitrary network calls by default. You must declare <code>http:post<\/code>codecodecodecode with a specific domain in the manifest. The plugin only talks to one API endpoint.<\/p>\n<p><strong>What to tell your AI agent:<\/strong> &#8220;Build a sandbox plugin that listens to <code>post:save<\/code>codecodecodecode. Extract the first 1000 characters of content. Send a POST request to https:\/\/api.openai.com\/v1\/completions with a prompt asking for a 155-character meta description. Write the response to the <code>seo.metaDescription<\/code>codecodecodecode field. Capabilities: <code>read:content<\/code>codecodecodecode, <code>write:content<\/code>codecodecodecode, <code>http:post<\/code>codecodecodecode.&#8221;<\/p>\n<h2>3. Scheduled Email Newsletter Digests<\/h2>\n<p><strong>The problem:<\/strong> EmDash has no built-in email campaign system. WordPress sites rely on Mailchimp plugins that don&#8217;t exist here.<\/p>\n<p><strong>The plugin:<\/strong> A sandbox plugin that runs on a cron-like schedule (every 7 days). It queries posts published in the last week, formats them into an HTML email, and sends it to a list of subscribers stored in a custom content type.<\/p>\n<p><strong>The technical detail:<\/strong> Dynamic workers cold-start in milliseconds. A scheduled plugin that runs weekly consumes near-zero billable compute. Compare that to a WordPress cron job hitting a PHP server.<\/p>\n<p><strong>What to tell your AI agent:<\/strong> &#8220;Create a plugin with a scheduled hook. Query all posts with status &#8216;published&#8217; from the last 7 days. Generate an HTML email template with titles and excerpts. Send it via the <code>email:send<\/code>codecodecodecode capability to all entries in the &#8216;subscribers&#8217; collection. Capabilities: <code>read:content<\/code>codecodecodecode, <code>email:send<\/code>codecodecodecode, <code>read:subscribers<\/code>codecodecodecode.&#8221;<\/p>\n<h2>4. Form Submission Spam Filter With Turnstile<\/h2>\n<p><strong>The problem:<\/strong> EmDash ships with a form plugin, but no built-in spam protection. Your portfolio site&#8217;s contact form fills with garbage.<\/p>\n<p><strong>The plugin:<\/strong> A sandbox plugin that intercepts form submissions before they&#8217;re saved. It validates a Cloudflare Turnstile token attached to the submission. If the token is missing or invalid, the submission is discarded with no database write.<\/p>\n<p><strong>What makes this possible:<\/strong> Turnstile is free. The plugin only needs one <code>http:post<\/code>codecodecodecode capability to verify the token against Cloudflare&#8217;s API. No CAPTCHA UI changes needed on the frontend.<\/p>\n<p><strong>What to tell your AI agent:<\/strong> &#8220;Build a plugin that hooks into <code>form:submit<\/code>codecodecodecode. Extract the <code>turnstileToken<\/code>codecodecodecode field from the submission payload. Send a POST request to https:\/\/challenges.cloudflare.com\/turnstile\/v0\/siteverify with the token and secret key. If the response indicates failure, delete the submission. Capabilities: <code>read:form<\/code>codecodecodecode, <code>delete:form<\/code>codecodecodecode, <code>http:post<\/code>codecodecodecode.&#8221;<\/p>\n<h2>5. Auto-Tagging Media Uploads<\/h2>\n<p><strong>The problem:<\/strong> Every uploaded image sits in the media library with no alt text, no tags, no description. Accessibility and SEO suffer.<\/p>\n<p><strong>The plugin:<\/strong> On <code>media:upload<\/code>codecodecodecode, the plugin reads the image file (via <code>read:media<\/code>codecodecodecode), extracts metadata, and writes a human-readable description to the media entry using a simple lookup table or a local classification model.<\/p>\n<p><strong>The information gain:<\/strong> This plugin doesn&#8217;t need an external AI API. You can embed a small lookup table that maps common image dimensions, file types, and naming patterns to descriptions. A file named &#8220;team-photo-2025.jpg&#8221; gets tagged &#8220;Team photo from 2025.&#8221; No network calls, no latency, zero ongoing cost.<\/p>\n<p><strong>What to tell your AI agent:<\/strong> &#8220;Create a plugin on <code>media:upload<\/code>codecodecodecode that reads the file name and file type from the media metadata. Apply a simple pattern: if the filename contains &#8216;team&#8217; or &#8216;group&#8217;, set description to &#8216;Team photo&#8217;. If it contains &#8216;logo&#8217;, set description to &#8216;Company logo&#8217;. Write the result to the media entry. Capabilities: <code>read:media<\/code>codecodecodecode, <code>write:media<\/code>codecodecodecode.&#8221;<\/p>\n<h2>6. Custom Analytics Dashboard<\/h2>\n<p><strong>The problem:<\/strong> EmDash has no analytics. You&#8217;re guessing which posts perform.<\/p>\n<p><strong>The plugin:<\/strong> A sandbox plugin that logs a <code>page:view<\/code>codecodecodecode event to a D1 database table every time a post is rendered. It exposes a simple admin panel widget showing top posts by views in the last <a href=\"https:\/\/overcentral.com\/en\/ai-influencers-fail-30-days-96592\/\" title=\"Why Most AI Influencers Fail to Earn in 30 Days\" data-iacss-internal=\"1\">30 days<\/a>.<\/p>\n<p><strong>Why this matters for billing:<\/strong> Each page view triggers a single D1 write. At 10 million requests per month on the $5 plan, a personal blog won&#8217;t crack the billing ceiling. But this is where the serverless cost concern becomes real for high-traffic sites\u2014every view is a metered action.<\/p>\n<p><strong>What to tell your AI agent:<\/strong> &#8220;Build a plugin that registers a <code>page:render<\/code>codecodecodecode hook. Increment a counter in the D1 database for the current post ID. Add an admin widget that queries the top 10 posts by view count and displays them as a list. Capabilities: <code>read:content<\/code>codecodecodecode, <code>write:d1<\/code>codecodecodecode.&#8221;<\/p>\n<h2>7. Simple Paywall With 402 Payments<\/h2>\n<p><strong>The problem:<\/strong> You want to charge for premium content. WordPress needs a subscription plugin. EmDash supports the 402 payment protocol natively.<\/p>\n<p><strong>The plugin:<\/strong> A sandbox plugin that checks whether a post belongs to the &#8220;premium&#8221; category. If yes, it intercepts the render and returns a 402 Payment Required response with a Lightning Invoice or a standard payment request. Paid requests get a signed token that bypasses the block for 24 hours.<\/p>\n<p><strong>The nuance:<\/strong> This isn&#8217;t a full membership system. It&#8217;s a single HTTP status code and a token check. But it&#8217;s native to the platform\u2014no Stripe plugin, no WooCommerce. The 402 protocol is built into the EmDash core.<\/p>\n<p><strong>What to tell your AI agent:<\/strong> &#8220;Create a plugin on <code>post:render<\/code>codecodecodecode that checks the post&#8217;s categories. If the category slug is &#8216;premium&#8217;, check for a valid <code>x-pay-token<\/code>codecodecodecode header. If missing, return a 402 status with a payment URL. Capabilities: <code>read:content<\/code>codecodecodecode, <code>read:categories<\/code>codecodecodecode.&#8221;<\/p>\n<h2>The Pattern That Makes This Work<\/h2>\n<p>Every plugin above follows the same structure: a hook, a capability manifest, and a single-purpose function. The AI agent writes the code. You review the capabilities list. The dynamic worker enforces the boundary.<\/p>\n<p>The mistake beginners make is asking for too much at once. &#8220;Build me a full e-commerce system.&#8221; That&#8217;s 50 plugins. Start with one hook, one capability, one output. Test it in the playground. Then expand.<\/p>\n<p>WordPress took 20 years to accumulate 60,000 plugins. EmDash has zero today. That&#8217;s not a weakness. It&#8217;s a canvas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cloudflare&#8217;s EmDash CMS launched as version 0.1.0. The plugin marketplace sits empty. That&#8217;s not a bug\u2014it&#8217;s an opening. Because EmDash ships with a built-in MCP server and agent skills files, you can generate plugins using natural language. No PHP required. No WordPress hooks to memorize. The sandboxed runtime handles security for you. Here are seven [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":99176,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98011.png","fifu_image_alt":"7 EmDash Plugins You Can Build With AI Right Now (Even If","footnotes":""},"categories":[31],"tags":[],"class_list":["post-98011","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98011.png","fifu_image_alt":"7 EmDash Plugins You Can Build With AI Right Now (Even If","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/comments?post=98011"}],"version-history":[{"count":1,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98011\/revisions"}],"predecessor-version":[{"id":99177,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98011\/revisions\/99177"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/99176"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=98011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=98011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=98011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}