Skip to content
Content
Skill

/creating-plugins

Create EmDash CMS plugins with sandboxed hooks, routes, storage, content and media APIs, MCP tools, and declarative admin UI, or native React and Astro extensions. Use when scaffolding or implementing an EmDash plugin.

BOOST
From plugin
emdash-cms-emdash
13k9 skills1 MCP
Install
$ npx -y skills add emdash-cms/emdash --skill creating-plugins --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/creating-plugins

Context preview

The summary Claude sees to decide when to auto-load this skill.

Create EmDash CMS plugins with sandboxed hooks, routes, storage, content and media APIs, MCP tools, and declarative admin UI, or native React and Astro extensions. Use when scaffolding or implementing an EmDash plugin.

SKILL.md

creating-plugins.SKILL.md
name: creating-plugins
description: Create EmDash CMS plugins with sandboxed hooks, routes, storage, content and media APIs, MCP tools, and declarative admin UI, or native React and Astro extensions. Use when scaffolding or implementing an EmDash plugin.

Creating EmDash plugins

Build against the API that reaches the intended execution mode. Source types and production-boundary tests take precedence over examples in this skill when they disagree.

Choose a format

| Format | Runtime source | Admin UI | Distribution | | --------- | --------------------------------------------------- | --------------------------------------------------------- | ---------------------------- | | Sandboxed | `src/plugin.ts` default-exports a `SandboxedPlugin` | Block Kit pages, widgets, saved-entry panels, and actions | Plugin CLI and registry | | Native | `definePlugin()` / `createPlugin()` | React, Block Kit, and Astro components | Trusted site dependency only |

Use a sandboxed plugin unless the feature needs host-process access, React admin code, Astro rendering components, raw page fragments, or custom Portable Text block definitions. Native plugins run with the site's authority and cannot be installed from the registry.

Scaffold a sandboxed plugin

pnpm dlx @emdash-cms/plugin-cli init my-plugin
cd my-plugin
pnpm install
pnpm run test

The manifest is the identity and trust contract. Runtime hooks and routes live in `src/plugin.ts`; the CLI generates descriptors, manifests, and bundles. Do not create a separate descriptor factory or `sandbox-entry.ts`.

import type { SandboxedPlugin } from "emdash/plugin";

const plugin: SandboxedPlugin = {
	hooks: {
		"content:afterSave": async (event, ctx) => {
			ctx.log.info("Content saved", { id: event.content.id });
		},
	},
};

export default plugin;

Import authoring types from `emdash/plugin` with `import type`. Value imports are limited to lightweight helpers such as `pluginRoute()` and `pluginResponse()`, which the CLI bundles. Sandboxed runtime code can use Web APIs but not Node.js built-ins.

Declare access

Declare every host API in `emdash-plugin.jsonc`. Adding authority, exposing a route publicly, or adding MCP tools requires renewed administrator approval.

| Capability | Grants | | -------------------------------- | -------------------------------------------------------------------------- | | `schema:read` | Public collection and field definitions | | `admin.editor-draft:read` | Selected unsaved field values after an explicit editor interaction | | `admin.editor-draft:patch` | Host-validated unsaved field changes proposed for editor review | | `content:read` | Content identity, translations, and published public URLs | | `content:revisions:read` | Retained revision data; implies content read | | `content:write` | Create, update, delete, and translation creation; implies read | | `content:publish` | Revision-fenced publish, unpublish, schedule, and unschedule; implies read | | `content:restore` | Revision-fenced reads and restoration of trashed content | | `hooks.content-policy:register` | Pre-publish, pre-schedule, and pre-unpublish policy hooks | | `taxonomies:read` | Taxonomy definitions, terms, and entry assignments | | `taxonomies:write` | Term creation and assignment deltas; implies read | | `bylines:read` | Public byline profiles and single or batched entry credits | | `redirects:read` | Versioned redirect inspection | | `redirects:write` | Versioned redirect creation, update, and deletion; implies read | | `comments:read` | Stored non-trashed comments and their personal data | | `comments:moderate` | Expected-status moderation; implies read | | `media:read` | Ready-media metadata and authenticated asset URLs | | `media:bytes:read` | Bounded media bytes and content hashes | | `media:metadata:write` | Alt text, caption, and focal-point updates | | `media:write` | Upload and delete; implies media read | | `network:request` | `ctx.http.fetch()` restricted to `allowedHosts` | | `network:request:unrestricted` | `ctx.http.fetch()` without a host list | | `users:read` | User directory lookup; also required by comment hooks | | `email:send` | Email delivery when a transport is configured | | `hooks.email-transport:register` | Exclusive `email:deliver` hook | | `hooks.email-events:register` | Email before/after hooks | | `hooks.page-fragments:register` | Trusted-only page fragments; excluded from sandbox registration |

Settings, KV, declared storage, logging, and cron scheduling are plugin-scoped and need no capability. Use `ctx.settings` for user configuration, `ctx.kv` for internal key-value state, and declared `ctx.storage.<collection>` for queryable recor

Read more
Ships withemdash-cms-emdash

A full-stack TypeScript CMS built on Astro. EmDash takes the ideas that made WordPress dominant -- extensibility, admin UX, a plugin ecosystem -- and rebuilds them on serverless, type-safe foundations.

Get the whole plugin
Stats
13,476
Stars
1,281
Forks
Active
Maintenance
TypeScript
Language
MIT
License
3h ago
Last commit
6mo ago
Created
9h ago
Added

Repo: emdash-cms/emdash

Other skills on emdash-cms-emdash.