Skip to content

Commit 2d3f896

Browse files
authored
docs: correct plugin installation and registry guidance (emdash-cms#3036)
* docs: correct plugin operator guidance * docs: clarify plugin operator guidance * docs: make registry the sandboxed plugin source * docs: simplify registry setup guidance
1 parent a9c01a9 commit 2d3f896

6 files changed

Lines changed: 184 additions & 267 deletions

File tree

docs/src/content/docs/plugins/field-kit.mdx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
---
22
title: Field Kit
3-
description: Composable field widgets for json fields, configured through seed options.
3+
description: Configure composable widgets for JSON fields through seed options.
44
---
55

66
import { Aside } from "@astrojs/starlight/components";
77

8-
EmDash's `json` field type stores arbitrary structured data, edited by default through a single-line text input that takes raw JSON. **Field Kit** is a first-party plugin that ships four composable widgets for `json` fields, configured entirely through seed `options` so site builders can use them with seed schema alone.
8+
EmDash's `json` field type stores arbitrary structured data. Its default editor is a single-line input for raw JSON. Field Kit is a first-party native plugin that adds four widgets configured through field `options` in a seed file.
99

10-
<Aside type="tip">
11-
Field Kit widgets store **clean JSON**: the stored value is plain content data, so removing the plugin leaves valid content behind.
10+
<Aside type="note">
11+
Field Kit stores plain JSON in the field's existing column. Removing the plugin leaves the content
12+
data in place.
1213
</Aside>
1314

1415
## Installation
@@ -19,7 +20,7 @@ Install the package from npm:
1920
npm i @emdash-cms/plugin-field-kit
2021
```
2122

22-
The following configuration registers the plugin:
23+
Import `fieldKitPlugin`, call it, and add the result to `plugins: []`:
2324

2425
```typescript title="astro.config.mjs"
2526
import { defineConfig } from "astro/config";
@@ -42,7 +43,9 @@ Attach a widget to any `json` field by setting `widget` to `field-kit:<name>`. T
4243
"slug": "ingredients",
4344
"type": "json",
4445
"widget": "field-kit:list",
45-
"options": { "fields": [...] }
46+
"options": {
47+
"fields": [{ "key": "name", "label": "Name", "type": "text", "required": true }]
48+
}
4649
}
4750
```
4851

Lines changed: 104 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,168 +1,158 @@
11
---
2-
title: Installing Plugins
3-
description: Install plugins from the EmDash Marketplace or add them from code.
2+
title: Installing plugins
3+
description: Install sandboxed plugins from the EmDash registry or register plugins from npm.
44
---
55

6-
import { Aside, Steps, Tabs, TabItem } from "@astrojs/starlight/components";
6+
import { Aside, Steps } from "@astrojs/starlight/components";
77

8-
EmDash plugins can be installed in two ways: from the marketplace via the admin dashboard, or added directly in your Astro configuration. Marketplace plugins always run sandboxed; config-based plugins run sandboxed or in-process depending on which array they're declared in (`sandboxed: []` vs `plugins: []`).
8+
Administrators can install sandboxed plugins from the [plugin registry](/plugins/registry/) or register npm packages in `astro.config.mjs`. Config-based plugins can run in the sandbox or in the site process.
99

10-
## From the Marketplace
10+
## Prepare for admin installs
1111

12-
The admin dashboard includes a marketplace browser where you can search, install, and manage plugins.
12+
Registry installs require:
1313

14-
<Aside type="tip">
15-
EmDash also has an experimental, federated alternative to the central marketplace. See [The plugin registry](/plugins/registry/).
16-
</Aside>
17-
18-
### Prerequisites
14+
- An administrator account with the `plugins:manage` permission.
15+
- [Configured storage](/deployment/storage/) for downloaded plugin bundles.
16+
- An available sandbox runner.
1917

20-
To install marketplace plugins, your site needs:
18+
On Cloudflare Workers, use `sandbox()` from `@emdash-cms/cloudflare`:
2119

22-
1. **Sandbox runner configured** — Marketplace plugins run in an isolated runtime, which requires the sandbox runner. The following configuration enables it:
20+
```typescript title="astro.config.mjs"
21+
import { sandbox } from "@emdash-cms/cloudflare";
22+
import { defineConfig } from "astro/config";
23+
import emdash from "emdash/astro";
2324

24-
```typescript title="astro.config.mjs"
25-
import { defineConfig } from "astro/config";
26-
import emdash from "emdash/astro";
25+
export default defineConfig({
26+
integrations: [
27+
emdash({
28+
sandboxRunner: sandbox(),
29+
experimental: {
30+
registry: "https://registry.emdashcms.com",
31+
},
32+
}),
33+
],
34+
});
35+
```
2736

28-
export default defineConfig({
29-
integrations: [
30-
emdash({
31-
marketplace: "https://marketplace.emdashcms.com",
32-
sandboxRunner: "@emdash-cms/sandbox-cloudflare",
33-
}),
34-
],
35-
});
36-
```
37+
The Cloudflare runner uses Worker Loader to create a separate Worker for each plugin. It requires the Workers Paid plan and a `worker_loaders` binding named `LOADER`. Sandboxed plugins reach content, media, storage, network, and email APIs through `PluginBridge`, so the site's Worker entry point must export that class. The `*-cloudflare` templates include the binding and export. Follow the [Cloudflare sandbox setup](/deployment/plugin-sandbox/#cloudflare-workers) when adding the runner to an existing site.
3738

38-
On **Cloudflare Workers**, sandboxing uses the Dynamic Worker Loader API (no additional setup needed). On **Node.js**, install the workerd sandbox runner:
39+
On Node.js, install the runner and its `workerd` peer dependency:
3940

40-
```bash
41-
npm install @emdash-cms/sandbox-workerd
42-
```
41+
```bash
42+
npm install @emdash-cms/sandbox-workerd workerd
43+
```
4344

44-
Then pass the runner explicitly:
45+
The `workerd` process runs the plugin code separately from the Node.js server. Select the runner in the EmDash integration:
4546

46-
```typescript title="astro.config.mjs"
47-
emdash({
48-
marketplace: "https://marketplace.emdashcms.com",
49-
sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox",
50-
})
51-
```
47+
```typescript title="astro.config.mjs"
48+
import { defineConfig } from "astro/config";
49+
import emdash from "emdash/astro";
5250

53-
In development, install `miniflare` as a dev dependency for faster sandbox startup:
51+
export default defineConfig({
52+
integrations: [
53+
emdash({
54+
sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox",
55+
experimental: {
56+
registry: "https://registry.emdashcms.com",
57+
},
58+
}),
59+
],
60+
});
61+
```
5462

55-
```bash
56-
npm install -D miniflare
57-
```
63+
See [Plugin sandbox](/deployment/plugin-sandbox/) for development setup, runtime requirements, resource limits, and unavailable-runner errors on both platforms.
5864

59-
The bindings, resource limits, and failure modes of each runner are described in [Plugin Sandbox](/deployment/plugin-sandbox/).
65+
## Install from the registry
6066

61-
2. **Admin access** — Only administrators can install or remove plugins.
67+
<Steps>
6268

63-
### Browse and Install
69+
1. Open **Registry** in the admin panel.
70+
2. Search for a plugin and open its detail page.
71+
3. Select a release and review its publisher, metadata, requested permissions, and verification status.
72+
4. Select **Install**.
73+
5. Review the verified release identifiers and permissions in the consent dialog, then confirm.
6474

65-
<Steps>
66-
1. Open the admin panel and navigate to **Plugins > Marketplace**
67-
2. Browse or search for a plugin
68-
3. Click the plugin card to see its detail page — README, screenshots, capabilities, and security audit results
69-
4. Click **Install**
70-
5. Review the capability consent dialog — this shows what the plugin will be able to access
71-
6. Confirm the installation
7275
</Steps>
7376

74-
The plugin will be downloaded, stored in your site's R2 bucket, and loaded into the sandbox runner. It's active immediately.
77+
EmDash verifies the publisher's current signed records and checks the downloaded bundle before loading it through the sandbox runner. The plugin appears under **Plugins**, where you can disable or configure it. See [The plugin registry](/plugins/registry/#install-a-registry-plugin) for the complete verification and trust model.
78+
79+
## Review permissions
7580

76-
### Capability Consent
81+
The consent dialog shows every permission declared by the plugin. Common permissions include:
7782

78-
Before installation, you'll see a dialog listing what the plugin needs access to:
83+
| Permission | Access granted |
84+
| ----------------- | ----------------------------------------------- |
85+
| `content:read` | Read site content |
86+
| `content:write` | Create, update, and delete content |
87+
| `media:read` | Read media records and files |
88+
| `media:write` | Upload, replace, and delete media |
89+
| `network:request` | Send requests to the plugin's allowed host list |
7990

80-
| Capability | What it means |
81-
| ---------- | ------------- |
82-
| `content:read` | Read your content |
83-
| `content:write` | Create, update, and delete content |
84-
| `media:read` | Access your media library |
85-
| `media:write` | Upload and manage media |
86-
| `network:request` | Make network requests to specific hosts |
91+
The dialog also identifies plugin routes exposed as Model Context Protocol (MCP) tools when a plugin declares them. See [Capabilities and security](/plugins/creating-plugins/capabilities/) for the complete permission model.
8792

8893
<Aside type="caution">
89-
Only install plugins from authors you trust. The capability system limits what a sandboxed plugin can access, but a plugin with `content:write` can modify any content on your site.
94+
Install code only from publishers you trust. Runtime isolation and capability checks limit a
95+
sandboxed plugin, but an approved permission still authorizes the described operation. For
96+
example, `content:write` allows the plugin to change content.
9097
</Aside>
9198

92-
### Security Audit
99+
## Update a plugin
93100

94-
Every plugin version in the marketplace has been through an automated security audit. The audit verdict appears on the plugin card:
101+
<Steps>
95102

96-
- **Pass** — No issues found
97-
- **Warn** — Minor concerns flagged (review the findings)
98-
- **Fail** — Significant security issues detected
103+
1. Open **Plugins** in the admin panel.
104+
2. Select **Check for updates**.
105+
3. Select **Update** on a registry plugin with an available release.
106+
4. Review the consent dialog, then confirm the update.
99107

100-
You can view the full audit report on the plugin's detail page, including individual findings and their severity.
108+
</Steps>
101109

102-
### Updates
110+
Registry updates require another confirmation when they add permissions or MCP tools, or when a route changes from authenticated to public. EmDash leaves the installed version in place until you approve the change.
103111

104-
When a newer version of an installed plugin is available:
112+
## Uninstall a plugin
105113

106-
1. Go to **Plugins** in the admin panel
107-
2. Marketplace plugins show an **Update available** badge
108-
3. Click **Update** to see the changelog and any capability changes
109-
4. If the new version requires additional capabilities, you'll see a diff and need to approve
110-
5. Confirm to update
114+
<Steps>
111115

112-
<Aside type="note">
113-
Updates that add new capabilities require explicit approval. If a plugin that previously only read content now wants to make network requests, you'll see the new capability highlighted before confirming.
114-
</Aside>
116+
1. Open **Plugins** in the admin panel and expand the installed plugin.
117+
2. Select **Uninstall**.
118+
3. Select **Also delete plugin storage data** only if you do not need the plugin's stored data for a later reinstall.
119+
4. Confirm the uninstall.
115120

116-
### Uninstalling
121+
</Steps>
117122

118-
1. Go to **Plugins** in the admin panel
119-
2. Click the marketplace plugin you want to remove
120-
3. Click **Uninstall**
121-
4. Choose whether to keep or delete the plugin's stored data
122-
5. Confirm
123+
EmDash removes the installed bundle and stops loading the plugin. Plugin storage data remains by default.
123124

124-
The plugin's sandbox code is removed from your R2 bucket and it stops running immediately.
125+
## Install from npm
125126

126-
## From Configuration
127+
Native plugins and config-managed sandboxed plugins install as npm dependencies. Follow the package's instructions to choose `plugins: []` or `sandboxed: []`.
127128

128-
Native plugins — your own code, or packages installed via npm — are added directly to the Astro config. The following example registers the SEO plugin:
129+
The following example registers the native Field Kit plugin:
129130

130131
```typescript title="astro.config.mjs"
131132
import { defineConfig } from "astro/config";
132133
import emdash from "emdash/astro";
133-
import seoPlugin from "@emdash-cms/plugin-seo";
134+
import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit";
134135

135136
export default defineConfig({
136-
integrations: [
137-
emdash({
138-
plugins: [
139-
seoPlugin({ generateSitemap: true }),
140-
],
141-
}),
142-
],
137+
integrations: [
138+
emdash({
139+
plugins: [fieldKitPlugin()],
140+
}),
141+
],
143142
});
144143
```
145144

146-
Native plugins:
145+
Config-managed plugins change when you update the npm dependency and deploy the site. They cannot be installed or removed from the admin panel.
147146

148-
- Run in-process (not sandboxed)
149-
- Have full access to Node.js APIs
150-
- Are loaded at build time and on every server start
151-
- Cannot be installed or removed from the admin UI
147+
## Choose an install method
152148

153-
<Aside type="tip">
154-
Use native plugins only when you need features that require build-time integration: React admin pages, Portable Text rendering components, or page fragment injection. For everything else, prefer sandboxed plugins -- they can be installed, updated, and removed from the admin panel.
155-
</Aside>
149+
| | Registry | npm with `sandboxed: []` | npm with `plugins: []` |
150+
| ---------------------------- | ------------------------------------------- | --------------------------------- | ----------------------------- |
151+
| Install and update | Admin panel | Dependency change and deploy | Dependency change and deploy |
152+
| Execution | Configured sandbox runner | Configured sandbox runner | Site process |
153+
| Access to EmDash | Only declared plugin APIs | Only declared plugin APIs | Declared plugin APIs plus direct process access |
154+
| Node.js APIs and direct `fetch()` | Unavailable | Unavailable | Available |
155+
| React admin components | Unavailable | Unavailable | Available |
156+
| Portable Text renderers | Unavailable | Unavailable | Available |
156157

157-
## Marketplace vs. config — when to use which
158-
159-
| | Marketplace (sandboxed) | Config (native or in-process sandboxed) |
160-
| --- | --- | --- |
161-
| **Install method** | One-click in admin UI | Code change + `npm install` + deploy |
162-
| **Execution** | Sandbox runtime via the configured runner | In-process (or sandboxed if listed under `sandboxed: []` and a runner is available) |
163-
| **Capabilities** | Enforced by the sandbox bridge — `ctx.*` gating plus runtime isolation | `ctx.*` gating only (in-process plugins can bypass via direct `fetch()`, env, imports) |
164-
| **Node.js APIs** | Not available | Full access (in-process only) |
165-
| **React admin pages** | No (Block Kit instead) | Yes (native plugins) |
166-
| **PT rendering components** | No | Yes (native plugins) |
167-
| **Updates** | One-click in admin | Version bump + deploy |
168-
| **Best for** | Most plugins | Plugins needing build-time integration |
158+
Use a native plugin when it needs React admin components, Portable Text renderers, page fragments, or direct access to the site process. Use a sandboxed plugin when it can work through the declared [plugin APIs](/plugins/creating-plugins/choosing-a-format/).

docs/src/content/docs/plugins/overview.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Plugins
3-
description: Extend EmDash with hooks, storage, settings, admin pages, and API routes.
3+
description: Choose, install, and operate sandboxed or native EmDash plugins.
44
---
55

66
import { Aside, Card, CardGrid, LinkCard } from "@astrojs/starlight/components";
@@ -34,10 +34,10 @@ Plugins extend EmDash through a defined extension surface. They can react to con
3434

3535
EmDash plugins come in two formats:
3636

37-
- **Sandboxed plugins** run in an isolated runtime managed by a configurable sandbox runner. They can be installed from the marketplace with one click, are subject to capability and resource enforcement, and reach only the APIs they declare. This is the recommended choice for most plugins.
38-
- **Native plugins** run in the same process as your Astro site. They have full access to the runtime, can ship React admin pages and Portable Text rendering components, and inject HTML into public pages. They install via a code change plus a deploy, and run from npm rather than the marketplace.
37+
- **Sandboxed plugins** run in a separate runtime managed by a configured sandbox runner. Administrators can install them from the plugin registry, and site developers can register them under `sandboxed: []` in `astro.config.mjs`. The runner limits plugins to their declared EmDash APIs and applies the resource limits supported by the platform.
38+
- **Native plugins** run in the same process as your Astro site. They have full access to the runtime, can ship React admin pages and Portable Text rendering components, and inject HTML into public pages. They install from npm through `astro.config.mjs` and require a deploy.
3939

40-
If you're installing a plugin someone else built, you almost always want sandboxed. If you're building one yourself, see [Choosing a plugin format](/plugins/creating-plugins/choosing-a-format/).
40+
Prefer a sandboxed plugin unless it needs React admin pages, Portable Text rendering components, page fragments, or direct access to the site process. If you're building a plugin, see [Choosing a plugin format](/plugins/creating-plugins/choosing-a-format/).
4141

4242
## For site operators
4343

@@ -46,7 +46,7 @@ If you want to install or configure plugins on your site:
4646
<LinkCard
4747
title="Installing plugins"
4848
href="/plugins/installing/"
49-
description="Install from the marketplace, enable, configure settings."
49+
description="Choose an install source, configure the sandbox, review permissions, and manage updates."
5050
/>
5151

5252
## For plugin authors

0 commit comments

Comments
 (0)