Skip to content

Dashboard contributions

Plugins contribute typed page descriptors and service callbacks. They do not register Hono routes or return arbitrary JSX, so the Web plugin retains authorization, validation, CSRF, audit, layout, and error isolation.

import { z } from "zod";
import { defineDashboardContributionV2 } from "popii-framework/plugins";
export const dashboard = defineDashboardContributionV2({
version: 2,
pluginId: "example",
label: "Example",
icon: "activity",
member: {
pages: [{
id: "overview",
label: "Overview",
layout: "overview",
audience: "member",
async load(context) {
return {
fields: [
{ label: "User", value: context.userId },
{ label: "Status", value: "Ready", tone: "success" },
],
};
},
actions: [{
id: "refresh",
label: "Refresh",
intent: "primary",
schema: z.object({}),
concurrency: "none",
rateLimit: "write",
audit: { action: "example.refresh", targetType: "example" },
async execute() {
return { message: "Refreshed" };
},
}],
}],
},
});

Attach the contribution to the plugin’s dashboard property. Layouts include overview, media, inbox, directory, detail, editor, guided-setup, timeline, analytics, and composite. Page and action IDs must be lowercase URL-safe identifiers. Duplicate IDs fail startup, contributions freeze at readiness, and every mutation declares concurrency, rate-limit, validation, and audit behavior.

Existing beta contributions are normalized internally while built-ins migrate. New plugins should use the v2 helper; plugins still cannot register Hono routes, JSX, scripts, cookies, headers, or raw database queries.

Contribution contexts never include cookies, raw headers, session tokens, OAuth tokens, Web SQLite repositories, or Discord.js objects. Guild callbacks receive a guild ID only after Popii has authorized the request.