Skip to main content

How Plugins Work

Plugins are standalone ES modules (.js files) that export a meta object and a setup function.
export const meta = {
  id: 'my-plugin',
  name: 'My Plugin',
  version: '1.0.0'
};

export function setup(api) {
  // api.boardEl, api.bus, api.storage, api.container, etc.
}

export function teardown() {
  // Optional: clean up on unload
}

Loading Process

1

Registry Read

Core reads the plugin registry from localStorage.
2

Plugin Manager Check

If the Plugin Manager is missing or disabled, it’s auto-installed/enabled from its default GitHub URL.
3

Deduplication

Duplicate plugin IDs are removed from the registry.
4

Filter Enabled

Only plugins with enabled: true are loaded.
5

Import

Each plugin is loaded via dynamic import(). For cross-origin URLs, the code is fetched and loaded via a blob URL (handles CORS).
6

Validation

Core checks that the module exports meta (with id, name, version) and setup (a function).
7

Permissions

Permissions are set on the plugin (system plugins get elevated access).
8

Setup

plugin.setup(api) is called with a 5-second timeout.
9

Event

plugin:loaded event is emitted. After all plugins load, board:allPluginsLoaded fires.

The meta Object

FieldRequiredDescription
idUnique identifier. Use kebab-case
nameDisplay name in Plugin Manager
versionSemantic version (e.g., "1.0.0")
compatCore version compatibility range (e.g., ">=3.3.0")

Plugin Management

Installing

await api.installPlugin('my-plugin', 'https://example.com/plugin.js', 'My Plugin');

Toggling

await api.togglePlugin('my-plugin');  // enable ↔ disable

Deleting

api.deletePlugin('my-plugin');  // permanent removal

Reloading

await api.reloadPlugin('my-plugin');  // unload + reload

Restarting

await api.restart();  // unload all + reload all enabled

Unloading

When a plugin is disabled or deleted:
  1. plugin.teardown() is called (if exported)
  2. The plugin’s container is removed from the DOM
  3. plugin:unloaded event is emitted
Always export a teardown() function for cleanup logic — clearing intervals, removing event listeners, removing injected CSS, etc.
let interval = null;
let currentApi = null;

export function setup(api) {
  currentApi = api;
  interval = setInterval(() => console.log('tick'), 1000);
  api.injectCSS(meta.id, `.my-plugin { color: red; }`);
}

export function teardown() {
  clearInterval(interval);
  currentApi?.removeCSS(meta.id);
}

Plugin Manager

The Plugin Manager is itself a plugin. It provides:
  • Installed Plugins tab — view, toggle, delete installed plugins
  • Community Store tab — browse and install from GitHub
  • Manual Install — paste any URL to install a plugin
  • Docs link — links to the official documentation
Access it by right-clicking anywhere on the board.

Plugin Manager Features

  • Cannot be deleted or paused (system protected)
  • Auto-installed on first boot
  • Auto-re-enabled if disabled
  • Registers its own UI slot system via api.registerUI()

Security

Trusted Sources

Plugins are checked against allowed sources:
SourceDescription
systemCore/official plugins
registryInstalled from the Community Store
manualInstalled via URL by the user
Plugins with unknown sources are blocked from loading.

Permissions

The Plugin Manager gets elevated permissions to manage other plugins. See Permissions for details.

Setup Timeout

Each plugin has a 5-second timeout for its setup() function. If it exceeds this, the plugin is considered failed and an error notification is shown.