Files
Toju/docs-site/docs/plugin-development/manifest.md
2026-04-29 17:15:01 +02:00

4.2 KiB

sidebar_position
sidebar_position
2

Manifest Model

The manifest is the source of truth for plugin identity, compatibility, runtime shape, capabilities, data, events, UI hints, and distribution metadata.

type TojuPluginInstallScope = 'client' | 'server';
type PluginEventDirection = 'clientToServer' | 'serverRelay' | 'p2pHint';
type PluginEventScope = 'server' | 'channel' | 'user' | 'plugin';

type PluginCapabilityId =
  | 'profile.read'
  | 'profile.write'
  | 'users.read'
  | 'users.manage'
  | 'roles.read'
  | 'roles.manage'
  | 'messages.read'
  | 'messages.send'
  | 'messages.editOwn'
  | 'messages.deleteOwn'
  | 'messages.moderate'
  | 'messages.sync'
  | 'channels.read'
  | 'channels.manage'
  | 'server.read'
  | 'server.manage'
  | 'p2p.data'
  | 'p2p.media'
  | 'media.playAudio'
  | 'media.addAudioStream'
  | 'media.addVideoStream'
  | 'audio.volume'
  | 'audio.effects'
  | 'ui.settings'
  | 'ui.pages'
  | 'ui.sidePanel'
  | 'ui.channelsSection'
  | 'ui.embeds'
  | 'ui.dom'
  | 'storage.local'
  | 'storage.serverData.read'
  | 'storage.serverData.write'
  | 'events.server.publish'
  | 'events.server.subscribe'
  | 'events.p2p.publish'
  | 'events.p2p.subscribe';

interface TojuPluginManifest {
  schemaVersion: 1;
  id: string;
  title: string;
  description: string;
  version: string;
  kind: 'client' | 'library';
  scope?: TojuPluginInstallScope;
  apiVersion: string;
  compatibility: {
    minimumTojuVersion: string;
    maximumTojuVersion?: string;
    verifiedTojuVersion?: string;
  };
  entrypoint?: string;
  bundle?: {
    url: string;
    entrypoint?: string;
  };
  readme?: string;
  homepage?: string;
  bugs?: string;
  changelog?: string;
  license?: string;
  authors?: {
    name: string;
    email?: string;
    url?: string;
  }[];
  capabilities?: PluginCapabilityId[];
  events?: {
    eventName: string;
    direction: PluginEventDirection;
    scope: PluginEventScope;
    maxPayloadBytes?: number;
    schema?: string;
  }[];
  data?: {
    key: string;
    schema?: string;
    scope: string;
    storage: 'local' | 'serverData';
  }[];
  relationships?: {
    after?: string[];
    before?: string[];
    conflicts?: string[];
    optional?: { id: string; versionRange?: string }[];
    requires?: { id: string; versionRange?: string }[];
  };
  load?: {
    priority?: 'bootstrap' | 'high' | 'default' | 'low';
  };
  pluginUser?: {
    avatar?: string;
    displayName: string;
    label?: string;
  };
  settings?: Record<string, unknown>;
  ui?: Record<string, unknown>;
}

Required Fields

Field Meaning
schemaVersion Manifest schema version. Currently 1.
id Stable plugin id. Use a reverse-DNS or package-style id.
title Human-readable plugin name.
description Short explanation shown in plugin UI.
version Plugin version.
kind client for runtime plugins, library for shared dependency-style entries.
apiVersion Plugin API version expected by the plugin.
compatibility.minimumTojuVersion Oldest app version the plugin supports.

Scope

scope: "client" installs the plugin for the current client. Omit scope for the same behavior.

scope: "server" marks a plugin as server-scoped. Server-scoped store entries can be installed to a chat server as requirements. Required server plugins are auto-installed for members when that server opens; optional requirements stay listed but do not auto-install.

Entrypoint and Bundle

Use entrypoint for a browser-resolvable module relative to the manifest. Use bundle.url when publishing a cached browser bundle through a plugin source manifest. Desktop installs cache bundle files into app data and load the cached manifest afterward.

Events

Every server or P2P plugin event should be declared before it is published or subscribed to.

{
  "events": [
    {
      "eventName": "poll:vote",
      "direction": "p2pHint",
      "scope": "channel",
      "maxPayloadBytes": 2048
    }
  ]
}

Data Declarations

Use data to document plugin-owned data keys and intended storage.

  • local maps to client-local plugin data.
  • serverData maps to local per-user/per-server plugin data.

Signal server HTTP persistence for arbitrary plugin data is disabled by design.