Skip to content

Create a plugin

New plugins use a stable manifest, Zod configuration schema, dependency/capability declarations, and disposable resources. They start in dependency order and stop in reverse order.

import { z } from "zod";
import type { RuntimePlugin } from "popii-framework/plugins";
export const examplePlugin: RuntimePlugin<{ endpoint: string }> = {
manifest: { id: "example", name: "Example", version: "1.0.0", popii: "^1.0.0", stability: "stable" },
configSchema: z.object({ endpoint: z.string().url() }),
setup({ config, provide }) {
provide("example.client", { endpoint: config.endpoint });
},
};

Use the plugin’s dashboard property to add member, guild-manager, or owner pages. See Dashboard contributions for the typed descriptor, validated action, audit, and security model.

Plugins must declare requirements, close resources during cleanup, avoid logging secrets, and expose only named capabilities. Popii records plugin-owned Discord listeners, removes them on rollback or shutdown, rejects command/component collisions, and freezes live registries after readiness. Every bundled non-Web plugin is created through the native manifest and Zod contract.

popii-reload, popii-sandbox, and popii-plugin-manager are deprecated and excluded from supported exports. Popii 1.0 does not support bot-controlled arbitrary code loading or package installation.