Plugin Manifest
The manifest declares your plugin to Pomavo: its identity, the widgets it embeds, the settings it collects, optional theme, and the resources it requests.
What the Manifest Is
The manifest is the contract between your plugin and the host. It declares who the plugin is, what UI it contributes, what configuration it needs, and what Pomavo resources it wants access to. The host stores the manifest when the plugin is published and re-validates it on every update.
interface PluginManifest {
id: string; // Stable unique id, e.g. "github-integration"
name: string; // Display name
version: string; // Semver, e.g. "1.2.0"
type?: 'theme' | 'ui' | 'general';
author: { name: string; url?: string };
description: string;
icon?: string; // URL or path to an icon
categories?: string[]; // e.g. ['integration', 'developer-tools']
lifecycle?: { url: string }; // POST endpoint for install/uninstall/update
setup?: { url: string; description?: string };
widgets?: PluginWidget[];
parameters?: PluginParameter[];
theme?: ThemeContribution; // Only for theme plugins
resources?: {
automations?: number[];
integrations?: { id: number; requestedPermissions: string[] }[];
};
}id, name, version, author, and description are required. Everything else is optional and depends on what your plugin does. A pure integration may have only a lifecycle.url; a UI plugin adds widgets; a theme plugin adds theme.
Widgets
Each widget is an embeddable UI panel. The host loads its url into a sandboxed iframe wherever the widget is placed, such as a panel on the ticket detail page.
interface PluginWidget {
id: string; // Unique within the plugin, e.g. "prs"
title: string; // Shown in the widget header
url: string; // Absolute URL the host embeds in the iframe
defaultHeight?: number;// Initial iframe height in px (before auto-resize)
}"widgets": [
{ "id": "prs", "title": "Pull Requests", "url": "https://my-plugin.example.com/widgets/prs", "defaultHeight": 320 },
{ "id": "commits", "title": "Commits", "url": "https://my-plugin.example.com/widgets/commits" }
]Parameters
Parameters are the settings the host collects from an admin when the plugin is installed or configured. Their values are persisted by the host and handed back to your widgets and backend as settings.
interface PluginParameter {
key: string; // Settings key
label: string; // Field label in the settings form
type: 'string' | 'secret' | 'boolean' | 'number' | 'select';
required?: boolean;
default?: string;
placeholder?: string;
description?: string;
options?: string[]; // For type: 'select'
}"parameters": [
{ "key": "org", "label": "GitHub Org", "type": "string", "required": true },
{ "key": "token", "label": "Access Token", "type": "secret", "required": true },
{ "key": "autoSync", "label": "Auto-sync commits", "type": "boolean", "default": "true" }
]Use type: 'secret' for tokens and passwords so the host masks the value in the settings UI. Never bake credentials into the manifest itself - collect them as parameters at install time.
Lifecycle & Setup URLs
lifecycle.url- the endpoint Pomavo POSTs install/uninstall/update events to. See Lifecycle & Auth.setup.url- an optional page the host links to so an admin can complete configuration that can't be expressed as simple parameters, such as an OAuth handshake.
"lifecycle": { "url": "https://my-plugin.example.com/lifecycle" },
"setup": { "url": "https://my-plugin.example.com/setup", "description": "Connect your GitHub account" }Resources
A plugin can declare the Pomavo resources it wants to bring in or access:
automations- ids of automation templates the plugin contributes.integrations- integration ids together with the permissions the plugin requests. The host surfaces these so the installing admin can review what access is being granted.
"resources": {
"integrations": [
{ "id": 12, "requestedPermissions": ["tickets:read", "tickets:write", "comments:write"] }
]
}Theme Plugins
A plugin with type: 'theme' or the theme category contributes one or more color themes instead of widgets. The host's theme loader registers these for users to select.
theme?: {
light: Record<string, string | string[]>;
dark: Record<string, string | string[]>;
font?: { sans?: string; mono?: string };
defaultVariantName?: string;
variants?: {
id: string;
name: string;
light: Record<string, string | string[]>;
dark: Record<string, string | string[]>;
font?: { sans?: string; mono?: string };
}[];
}Each light / dark map is a set of CSS custom-property values using the same tokens documented under Themes. Provide multiple named variants to ship a family of related themes in one plugin.
A Complete Example
{
"id": "github-integration",
"name": "GitHub",
"version": "1.0.0",
"type": "ui",
"icon": "https://gh-plugin.example.com/icon.png",
"author": { "name": "Pomavo", "url": "https://pomavo.dev" },
"description": "Link commits, branches, and pull requests to tickets.",
"categories": ["integration", "developer-tools"],
"lifecycle": { "url": "https://gh-plugin.example.com/lifecycle" },
"setup": { "url": "https://gh-plugin.example.com/setup", "description": "Connect your GitHub account" },
"parameters": [
{ "key": "org", "label": "GitHub Org", "type": "string", "required": true, "placeholder": "my-company" },
{ "key": "token", "label": "Access Token", "type": "secret", "required": true, "description": "A fine-grained token with repo read access." },
{ "key": "autoSync", "label": "Auto-sync commits", "type": "boolean", "default": "true" },
{ "key": "environment", "label": "Environment", "type": "select", "options": ["production", "staging"], "default": "production" }
],
"widgets": [
{ "id": "prs", "title": "Pull Requests", "url": "https://gh-plugin.example.com/widgets/prs", "defaultHeight": 320 },
{ "id": "commits", "title": "Commits", "url": "https://gh-plugin.example.com/widgets/commits" }
],
"resources": {
"automations": [7, 11],
"integrations": [
{ "id": 12, "requestedPermissions": ["tickets:read", "tickets:write", "comments:write"] }
]
}
}