Skip to content

manifest.json ​

Every plugin must ship a manifest.json at its root URL. Dissent fetches this when an admin installs a plugin via URL.

Example ​

json
{
  "id": "chess-stats",
  "name": "Chess.com Stats",
  "version": "1.2.0",
  "description": "Live chess rating and recent game history from Chess.com.",
  "context": ["sidebar", "profile"],
  "tier": 2,
  "url": "https://myplugins.example.com/chess-stats/index.html",
  "declared_permissions": ["fetch:external"],
  "allowed_fetch_domains": ["api.chess.com"],
  "config_schema": {
    "username": {
      "type": "string",
      "label": "Chess.com username",
      "required": true
    }
  }
}

Fields ​

id · string · required ​

Unique stable identifier for your plugin. Use lowercase letters, numbers, and hyphens. Once set, do not change — Dissent uses this to identify the plugin in the registry and across reinstalls.

Example: "chess-stats"


name · string · required ​

Display name shown in the marketplace and Server Settings.

Example: "Chess.com Stats"


version · string · required ​

Semantic version string.

Example: "1.2.0"


description · string · required ​

One or two sentences describing what the plugin does. Shown in the marketplace listing.

Example: "Live chess rating and recent game history from Chess.com."


context · string[] · required ​

Array of contexts this plugin supports. Valid values: "channel", "sidebar", "profile", "embed", "personal".

A "personal" plugin may declare only the permissions of the personal lane — see Personal Plugins.

A plugin whose context is only ["personal"] cannot be installed on a server: each person adds it from My plugins, and the node refuses a server install of it. List another context as well if it also belongs on servers.

Example: ["sidebar", "profile"]


tier · 1 | 2 | 3 · required ​

A label: 1 Passive, 2 Interactive, 3 Activity, shown in the marketplace, server settings and on the consent card. It grants no permissions and does not decide whether the consent card appears — declared_permissions does both. See Permissions.

Example: 1


url · string · required ​

The full URL to the plugin's index.html. This is snapshotted in the database at install time. If your domain changes, the plugin must be reinstalled.

Example: "https://myplugins.example.com/chess-stats/index.html"


config_schema · object · optional ​

Defines admin-configurable fields. Each key becomes an input in the plugin's config UI inside Server Settings. If null or omitted, the plugin has no admin configuration.

Each value is an object with:

PropertyTypeDescription
type"string" | "number" | "boolean"Input type
labelstringHuman-readable label shown in the config UI
requiredbooleanWhether the field must be filled before saving

Values the admin enters are accessible in your plugin as ctx.config.

The key is snake_case. The node reads config_schema and ignores configSchema.


allowed_fetch_domains · string[] · required to use Dissent.fetch() ​

The hostnames Dissent.fetch() may reach, e.g. ["api.chess.com"]. Matching is exact — example.com does not admit api.example.com — and applies to every redirect hop. Bare hostnames only: no scheme, port or path. With an empty list, every fetch is refused (the node answers domain not in plugin allowlist; the SDK call rejects with fetch failed). Some hosts are further gated by a server-level switch that the server owner must turn on.


declared_permissions · string[] · required for any plugin that uses a permission ​

The only permissions a user can grant, for every context. Exactly the permissions the plugin uses, e.g. ["storage:user", "game:saves", "overlay:context"]. The user approves this list; a later version that adds one shows Review permissions instead of granting it.


overlay · object · optional (personal plugins) ​

Panels this plugin adds to the desktop app's game overlay: games (catalog ids) and surfaces (id, title, layer "panel", anchor, size). The node validates it when the plugin is added. See Overlay Panels for every rule.


screenshots · string[] · optional ​

Array of image URLs shown in the marketplace listing. Recommended size: 1280×800px.


readme_url · string · optional ​

URL to a Markdown file rendered as the plugin's marketplace "About" page.