|
1 | 1 | --- |
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. |
4 | 4 | --- |
5 | 5 |
|
6 | | -import { Aside, Steps, Tabs, TabItem } from "@astrojs/starlight/components"; |
| 6 | +import { Aside, Steps } from "@astrojs/starlight/components"; |
7 | 7 |
|
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. |
9 | 9 |
|
10 | | -## From the Marketplace |
| 10 | +## Prepare for admin installs |
11 | 11 |
|
12 | | -The admin dashboard includes a marketplace browser where you can search, install, and manage plugins. |
| 12 | +Registry installs require: |
13 | 13 |
|
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. |
19 | 17 |
|
20 | | -To install marketplace plugins, your site needs: |
| 18 | +On Cloudflare Workers, use `sandbox()` from `@emdash-cms/cloudflare`: |
21 | 19 |
|
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"; |
23 | 24 |
|
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 | +``` |
27 | 36 |
|
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. |
37 | 38 |
|
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: |
39 | 40 |
|
40 | | - ```bash |
41 | | - npm install @emdash-cms/sandbox-workerd |
42 | | - ``` |
| 41 | +```bash |
| 42 | +npm install @emdash-cms/sandbox-workerd workerd |
| 43 | +``` |
43 | 44 |
|
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: |
45 | 46 |
|
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"; |
52 | 50 |
|
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 | +``` |
54 | 62 |
|
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. |
58 | 64 |
|
59 | | - The bindings, resource limits, and failure modes of each runner are described in [Plugin Sandbox](/deployment/plugin-sandbox/). |
| 65 | +## Install from the registry |
60 | 66 |
|
61 | | -2. **Admin access** — Only administrators can install or remove plugins. |
| 67 | +<Steps> |
62 | 68 |
|
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. |
64 | 74 |
|
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 |
72 | 75 | </Steps> |
73 | 76 |
|
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 |
75 | 80 |
|
76 | | -### Capability Consent |
| 81 | +The consent dialog shows every permission declared by the plugin. Common permissions include: |
77 | 82 |
|
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 | |
79 | 90 |
|
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. |
87 | 92 |
|
88 | 93 | <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. |
90 | 97 | </Aside> |
91 | 98 |
|
92 | | -### Security Audit |
| 99 | +## Update a plugin |
93 | 100 |
|
94 | | -Every plugin version in the marketplace has been through an automated security audit. The audit verdict appears on the plugin card: |
| 101 | +<Steps> |
95 | 102 |
|
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. |
99 | 107 |
|
100 | | -You can view the full audit report on the plugin's detail page, including individual findings and their severity. |
| 108 | +</Steps> |
101 | 109 |
|
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. |
103 | 111 |
|
104 | | -When a newer version of an installed plugin is available: |
| 112 | +## Uninstall a plugin |
105 | 113 |
|
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> |
111 | 115 |
|
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. |
115 | 120 |
|
116 | | -### Uninstalling |
| 121 | +</Steps> |
117 | 122 |
|
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. |
123 | 124 |
|
124 | | -The plugin's sandbox code is removed from your R2 bucket and it stops running immediately. |
| 125 | +## Install from npm |
125 | 126 |
|
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: []`. |
127 | 128 |
|
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: |
129 | 130 |
|
130 | 131 | ```typescript title="astro.config.mjs" |
131 | 132 | import { defineConfig } from "astro/config"; |
132 | 133 | import emdash from "emdash/astro"; |
133 | | -import seoPlugin from "@emdash-cms/plugin-seo"; |
| 134 | +import { fieldKitPlugin } from "@emdash-cms/plugin-field-kit"; |
134 | 135 |
|
135 | 136 | 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 | + ], |
143 | 142 | }); |
144 | 143 | ``` |
145 | 144 |
|
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. |
147 | 146 |
|
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 |
152 | 148 |
|
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 | |
156 | 157 |
|
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/). |
0 commit comments