Popii - v0.5.1
    Preparing search index...

    Plugins

    Plugins are how Popii extends the bot with additional functionality. They plug into the client lifecycle (setup, ready, reload, cleanup) and can augment pop context, register routes, hook into events, and more.

    Add plugins to the plugins array in popiiClient():

    import { popiiClient, sqlitePlugin, webPlugin, voicePlugin, errorHandlerPlugin } from "popii";

    const client = popiiClient({
    token: process.env.DISCORD_TOKEN!,
    plugins: [
    sqlitePlugin(),
    voicePlugin(),
    webPlugin({ port: 3000, dashboard: true }),
    errorHandlerPlugin(),
    ]
    });

    Plugins run in the order listed. Higher-priority plugins (set via the priority field on the plugin object) run first regardless of order.

    Plugin Import Purpose
    sqlitePlugin from "popii" Injects a Bun SQLite db into every pop
    mongoosePlugin from "popii" Connects Mongoose to MongoDB
    voicePlugin from "popii" Voice playback with queue, SponsorBlock, now-playing cards
    webPlugin from "popii" HTTP server, health check, metrics, web dashboard
    deskPlugin from "popii" Support ticket system
    popiiAiPlugin from "popii" AI assistant (OpenAI / Gemini / Anthropic)
    economyPlugin from "popii" Virtual currency, XP, inventory
    uiPlugin from "popii" Pagination, forms, interactive prompts
    payPlugin from "popii" Payment processing
    autoModPlugin from "popii" Automated moderation
    giveawayPlugin from "popii" Giveaway system
    canvasPlugin from "popii" Image generation
    lastFmPlugin from "popii" Last.fm scrobbling
    captchaPlugin from "popii" Verification captchas
    activityRotatorPlugin from "popii" Rotating bot status
    telemetryPlugin from "popii" Performance monitoring
    commandLoggerPlugin from "popii" Execution logging
    commandAnalyticPlugin from "popii" Usage analytics
    permissionGuardPlugin from "popii" Permission enforcement
    errorHandlerPlugin from "popii" Graceful error display
    reloadPlugin from "popii" Adds /reload slash command

    Install plugins from the marketplace with the CLI:

    bunx popii add economy       # installs popii-plugin-economy
    bunx popii search music # search the registry

    Or enable auto-discovery to load all installed popii-plugin-* packages automatically:

    const client = popiiClient({
    token: process.env.DISCORD_TOKEN!,
    autoDiscover: true,
    pluginConfig: {
    "popii-plugin-economy": { currencySymbol: "🪙" }
    }
    });

    A plugin is an object with a name and lifecycle hooks. The setup hook receives the PopiiClient instance once, at startup.

    import type { PopiiPlugin } from "popii";

    export function myPlugin(options: { greeting: string } = { greeting: "Hello" }): PopiiPlugin {
    return {
    name: "my-plugin",

    setup(client) {
    // Runs once at startup. Register listeners, patch the client, etc.
    client.onBroadcast("my-plugin:ping", (data) => {
    console.log("Received ping:", data);
    });
    },

    ready(client) {
    // Runs after the bot is connected to Discord.
    console.log(`${options.greeting} from my-plugin!`);
    },

    cleanup(client) {
    // Runs on shutdown. Clean up intervals, close connections, etc.
    }
    };
    }
    Hook When it runs
    setup(client) Before Discord connects — register listeners, create DB tables
    ready(client) After Discord connects — safe to use client.discord.guilds.cache
    reload(client) After a hot-reload — re-wrap commands with middleware, etc.
    cleanup(client) On graceful shutdown — clear intervals, close sockets
    onCommandExecute(pop, cmd) Before every command runs — useful for analytics
    onCommandError(err, pop) When a command throws — useful for error reporting
    onContextCreate(pop) When a pop context is created — inject data into context

    Expose settings that appear automatically in the web dashboard's server settings form:

    export function myPlugin(): PopiiPlugin {
    return {
    name: "my-plugin",
    settingsSchema: [
    {
    id: "welcomeChannel",
    label: "Welcome Channel",
    type: "channel",
    description: "Where to post welcome messages",
    category: "My Plugin"
    },
    {
    id: "enableGreeting",
    label: "Enable greeting messages",
    type: "boolean",
    default: true,
    category: "My Plugin"
    }
    ],
    setup(client) { /* ... */ }
    };
    }
    export function myPlugin(): PopiiPlugin {
    return {
    name: "my-plugin",
    setup(client) {
    (client as any)._pluginRoutes?.set("/my-plugin", async (req: Request, session: any, url: URL) => {
    return new Response(JSON.stringify({ ok: true }), {
    headers: { "Content-Type": "application/json" }
    });
    });
    }
    };
    }
    1. Use the plugin template
    2. Name your package popii-plugin-<name>
    3. Add a "popii" field in package.json with plugin metadata:
    {
    "name": "popii-plugin-my-feature",
    "popii": {
    "displayName": "My Feature",
    "description": "Adds my feature to Popii bots",
    "category": "features",
    "export": "myFeaturePlugin"
    }
    }