{"id":98097,"date":"2026-10-13T15:02:00","date_gmt":"2026-10-13T19:02:00","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=98097"},"modified":"2026-09-29T08:07:10","modified_gmt":"2026-09-29T12:07:10","slug":"emdash-plugins-ai-prompts-98097","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/emdash-plugins-ai-prompts-98097\/","title":{"rendered":"5 EmDash Plugins You Can Build With Zero Coding (Using AI Prompts)"},"content":{"rendered":"<p><a href=\"https:\/\/emdash.dev\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">EmDash CMS<\/a> from Cloudflare changes how plugins work. Every plugin runs in a sandboxed V8 isolate \u2014 it can&#8217;t touch your database, files, or network unless you explicitly allow it. That security model is the headline. But there&#8217;s a quieter revolution here: you can build plugins without writing a single line of code yourself. Give the right prompt to <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> coding agent \u2014 Claude, Cursor, or GitHub Copilot \u2014 and it generates a working plugin in seconds.<\/p>\n<p>The platform uses TypeScript and Astro. The plugin API is minimal. A plugin declares its capabilities in a manifest, registers hooks, and the runtime enforces the boundaries. That makes it ideal for AI generation. The scope is narrow, the pattern is predictable, and the output is safe by default.<\/p>\n<p>Below are five plugins you can build right now. Each includes the exact prompt you&#8217;d feed an agent, the capability manifest it needs, and the key insight that makes it work.<\/p>\n<h2>1. Email Notification on Publish<\/h2>\n<p>The simplest plugin to start with. When a post moves to &#8220;published,&#8221; send an email to the site admin. WordPress needs a plugin like Post SMTP or a third-party service. EmDash handles it with a single hook and a <code>sendEmail<\/code>codecodecodecode capability.<\/p>\n<p><strong>Prompt for the <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><\/p>\n<blockquote>\n<p>Generate an EmDash CMS plugin. Use <code>definePlugin<\/code> from the <code>@mdash\/plugins<\/code> library. The plugin ID is <code>email-on-publish<\/code>, version <code>0.0.1<\/code>. Capabilities: <code>read:content<\/code>, <code>send:email<\/code>. Register a hook on <code>post:publish<\/code>. Inside the hook, get the published post&#8217;s title and author email from the context. Then send an email to the admin address (hardcoded as <code>admin@example.com<\/code>). Subject line: &#8220;New post published: [title]&#8221;. Body: &#8220;A new post by [author] has been published.&#8221; Use the <code>email.send()<\/code> method from the context.<\/p>\n<\/blockquote>\n<p>blockquoteblockquoteblockquoteblockquote<\/p>\n<p><strong>Key insight:<\/strong> The agent writes the entire plugin \u2014 about 20 lines. The sandbox ensures the plugin can never read passwords or delete content, even if the AI introduces a bug. The <code>send:email<\/code>codecodecodecode capability is the only external access it gets.<\/p>\n<h2>2. Auto-Generate Alt Text for Images<\/h2>\n<p>Every uploaded image needs descriptive alt text. Manually adding it for dozens of images is tedious. A plugin can hook into the <code>media:upload<\/code>codecodecodecode event, call an AI vision API, and write the alt text back to the media record.<\/p>\n<p><strong>Prompt for the AI agent:<\/strong><\/p>\n<blockquote>\n<p>Create an EmDash plugin with ID <code>auto-alt-text<\/code>. Capabilities: <code>read:media<\/code>, <code>write:media<\/code>, <code>fetch:url<\/code>. Hook on <code>media:upload<\/code>. When a new image is uploaded, get its public URL from the context. Use the <code>fetch<\/code> capability to send that URL to the OpenAI API endpoint <code>https:\/\/api.openai.com\/v1\/chat\/completions<\/code> with a prompt &#8220;Describe this image in 10 words or less.&#8221; Parse the response and update the media record&#8217;s <code>alt<\/code> field using <code>context.media.update(id, { alt: description })<\/code>. Store the API key in a plugin secret.<\/p>\n<\/blockquote>\n<p>blockquoteblockquoteblockquoteblockquote<\/p>\n<p><strong>Key insight:<\/strong> The plugin declares <code>fetch:url<\/code>codecodecodecode to access an external API. That&#8217;s a deliberate permission \u2014 the sandbox blocks any other network traffic. The plugin cannot exfiltrate your database or call unknown endpoints. This is the pattern for any AI-powered feature.<\/p>\n<h2>3. Scheduled Content Expiry<\/h2>\n<p>WordPress has no built-in way to unpublish content after a set date. <a href=\"https:\/\/overcentral.com\/en\/wardogs-recon-myth-busted-81574\/\" title=\"The WARDOGS Recon Myth You Need to Stop Believing\" data-iacss-internal=\"1\">You need<\/a> a plugin or cron job. EmDash plugins can use <code>setInterval<\/code>codecodecodecode inside a worker \u2014 but workers are ephemeral. The better approach hooks into a periodic system event.<\/p>\n<p><strong>Prompt for the AI agent:<\/strong><\/p>\n<blockquote>\n<p>Build an EmDash plugin <code>content-expiry<\/code>. Capabilities: <code>read:content<\/code>, <code>write:content<\/code>. Register a hook on <code>system:tick<\/code> (fires every 5 minutes). On each tick, query all posts where a custom field <code>expiry_date<\/code> is set and is in the past. For each such post, change its status to <code>draft<\/code> and log the action. Add a UI field in the post editor sidebar that allows setting the expiry date as a datetime picker. Use the <code>fields.register<\/code> helper to add the field.<\/p>\n<\/blockquote>\n<p>blockquoteblockquoteblockquoteblockquote<\/p>\n<p><strong>Key insight:<\/strong> The plugin uses a system tick \u2014 not a cron job \u2014 because EmDash runs on serverless infrastructure. The hook fires on every instance that&#8217;s active, but the plugin&#8217;s sandbox prevents it from interfering with other instances. The custom field is defined in code, not in the database, so it survives migrations.<\/p>\n<h2>4. Content Sitemap for Custom Post Types<\/h2>\n<p>EmDash ships with SEO fields and a default sitemap, but only for pages and posts. If you create a custom content type (say &#8220;Projects&#8221; or &#8220;Reviews&#8221;), the sitemap ignores it. This plugin extends the sitemap to include all registered content types.<\/p>\n<p><strong>Prompt for the AI agent:<\/strong><\/p>\n<blockquote>\n<p>Write an EmDash plugin <code>custom-sitemap<\/code>. Capabilities: <code>read:content<\/code>, <code>read:content-types<\/code>. Hook on <code>sitemap:generate<\/code>. Inside the hook, iterate over all content types using <code>context.contentTypes.list()<\/code>. For each type, fetch all published items. Append each item&#8217;s URL (using the <code>slug<\/code> and the content type&#8217;s URL pattern) to the sitemap array returned by the hook. Ensure the output is valid XML.<\/p>\n<\/blockquote>\n<p>blockquoteblockquoteblockquoteblockquote<\/p>\n<p><strong>Key insight:<\/strong> The plugin reads the content type registry \u2014 a resource that WordPress plugins can&#8217;t access natively without custom tables. EmDash exposes it through the context API. The agent generates the loop and XML formatting automatically. No manual schema definition needed.<\/p>\n<h2>5. Webhook Relay to External Services<\/h2>\n<p>Businesses often need to forward new content to Slack, Discord, or a custom API. A webhook plugin listens for publish events and sends a JSON payload to a configurable URL.<\/p>\n<p><strong>Prompt for the AI agent:<\/strong><\/p>\n<blockquote>\n<p>Develop an EmDash plugin <code>webhook-relay<\/code>. Capabilities: <code>read:content<\/code>, <code>fetch:url<\/code>. Hook on <code>post:publish<\/code>. Get the post title, URL, and excerpt. Build a JSON payload. Send a POST request to a URL stored in a plugin setting (default: <code>https:\/\/hooks.slack.com\/services\/...<\/code>). Use <code>context.settings.get('webhook_url')<\/code> to load the URL. Return a success or failure message to the event log.<\/p>\n<\/blockquote>\n<p>blockquoteblockquoteblockquoteblockquote<\/p>\n<p><strong>Key insight:<\/strong> The agent creates a settings page automatically if you include <code>context.settings.register<\/code>codecodecodecode in the prompt. The plugin never sees your Slack token \u2014 it&#8217;s stored in Cloudflare&#8217;s encrypted key-value store. The <code>fetch:url<\/code>codecodecodecode capability limits it to exactly one domain.<\/p>\n<h2>Closing: The Real Power Is Composition<\/h2>\n<p>These five plugins are standalone. But EmDash&#8217;s architecture allows them to work together. The auto-alt-text plugin and the webhook relay can share the same <code>fetch:url<\/code>codecodecodecode capability without conflict. The content expiry plugin can trigger the email notification plugin through a shared event. And because every plugin is sandboxed, you can install all five without worrying about one breaking another.<\/p>\n<p>The AI prompt approach works because the EmDash plugin API is deliberately constrained. Each plugin has a single purpose, a clear capability boundary, and a predictable lifecycle. That makes it trivial for an agent to generate correct code \u2014 and impossible for that code to escalate privileges. Beginners get a working plugin in minutes. Experienced developers get a platform where AI-generated code is safe to deploy without human review.<\/p>\n<p>The next frontier? Point an MCP agent at your EmDash instance and say: &#8220;Build me a plugin that syncs new posts to my Notion database.&#8221; The agent reads the skills file, writes the plugin, and deploys it. That&#8217;s not a demo. That&#8217;s the product.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>EmDash CMS from Cloudflare changes how plugins work. Every plugin runs in a sandboxed V8 isolate \u2014 it can&#8217;t touch your database, files, or network unless you explicitly allow it. That security model is the headline. But there&#8217;s a quieter revolution here: you can build plugins without writing a single line of code yourself. Give [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":100443,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98097.png","fifu_image_alt":"5 EmDash Plugins You Can Build With Zero Coding (Using AI Prompts)","footnotes":""},"categories":[31],"tags":[],"class_list":["post-98097","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98097.png","fifu_image_alt":"5 EmDash Plugins You Can Build With Zero Coding (Using AI Prompts)","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98097","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=98097"}],"version-history":[{"count":1,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98097\/revisions"}],"predecessor-version":[{"id":100444,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98097\/revisions\/100444"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/100443"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=98097"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=98097"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=98097"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}