# Publish a community plugin (/docs/guides/authoring/publish-community-plugin)



Community plugins are npm packages that export an `EmailPlugin` factory. The docs site lists them from a static JSON registry; there is no hosted plugin service.

If your package sends through a new provider, use [Publish a community adapter](/docs/guides/authoring/publish-community-adapter) instead. Adapter packages still export plugins, but they need extra field-support and provider-mapping documentation.

## Package shape [#package-shape]

```txt
email-sdk-require-metadata/
  src/
    index.ts
    require-metadata.ts
    require-metadata.test.ts
  package.json
  README.md
```

Export the plugin factory from the package root.

```ts
export { requireMetadataPlugin } from "./require-metadata";
export type { RequireMetadataOptions } from "./require-metadata";
```

Apps should be able to use the package in one line inside `plugins`.

```ts
createEmailClient({
  plugins: [requireMetadataPlugin({ key: "tenantId" })],
});
```

## Package requirements [#package-requirements]

Use `@opencoredev/email-sdk` as a peer dependency.

```json
{
  "name": "email-sdk-require-metadata",
  "type": "module",
  "sideEffects": false,
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js"
    }
  },
  "peerDependencies": {
    "@opencoredev/email-sdk": "^0.4.0"
  }
}
```

Verified packages must not define `preinstall`, `install`, or `postinstall` scripts.

## Security expectations [#security-expectations]

Verified packages must be boring:

* Public source repository.
* npm trusted publishing or provenance.
* No install scripts.
* No binaries.
* Small runtime dependency surface.
* No network calls during import or plugin construction.
* Tests that prove the plugin registers with `createEmailClient`.

These checks reduce supply-chain risk, but they do not make third-party code risk-free.

## Registry entry [#registry-entry]

Add the package to `apps/fumadocs/content/community/plugins.json`.

```json
{
  "name": "Require metadata",
  "package": "email-sdk-require-metadata",
  "kind": "plugin",
  "status": "community",
  "description": "Blocks sends unless required metadata is present.",
  "href": "https://www.npmjs.com/package/email-sdk-require-metadata",
  "repo": "https://github.com/acme/email-sdk-require-metadata",
  "maintainer": "acme",
  "pluginId": "require-metadata"
}
```

Use `status: "verified"` only after the package passes the verification checklist for one published version.

## Verify locally [#verify-locally]

```bash
bun run community:check
```

CI runs the same registry check. Verified entries also get a package tarball audit in CI.

## Next [#next]

Adapter packages follow the same process, but should also document field support. See [Publish a community adapter](/docs/guides/authoring/publish-community-adapter).
