Twig plugins
A plugin is an ES module Twig imports by URL. It can add slash commands, render macros inside blocks, open a panel in the sidebar, own a screen of its own, read and write the graph, and listen for changes.
Installing one
- Open Plugins from Settings › More. Five ship with Twig and install with one press.
- Anything else goes in as a URL, under From a URL at the bottom of that screen.
- Twig imports the module and calls its default export, passing the API, and again each time the plugin is switched on.
- Turning a plugin off undoes everything it registered; so does removing it.
The smallest plugin that does something
export const name = 'Shout'
export default function (twig) {
twig.macros.add('shout', (args) => {
const el = document.createElement('strong')
el.textContent = args.toUpperCase()
return el
})
}Type {{shout hello}} in any block and it renders HELLO. There is nothing to clean up: switching the plugin off takes the macro with it, and whatever the default export returns is called then too.
Types
The API is typed in src/plugins/types.ts: TwigApi, TwigPlugin, and the Page and Block records it hands back. There is no published twig package to import it from, so a plugin written in TypeScript copies that one file next to its own source; it imports nothing. A plugin shipped as plain JavaScript needs no build step at all.
// twig-types.ts is a copy of src/plugins/types.ts
import type { TwigApi, TwigPlugin } from './twig-types.ts'
const plugin: TwigPlugin = (twig: TwigApi) => { /* … */ }
export default pluginWhere plugins are kept
| What | Where |
|---|---|
| The installed list | This browser’s localStorage, under twig.plugins: one list per device, not part of a backup export. |
| Sync installed plugins | Turned on under Sync in Settings, the list (each plugin’s address, name, whether it is on, and when that last changed) is also kept on the sync server under your account, so every device with the switch on installs, removes and switches plugins to match. Only the built-ins and https addresses travel. |
| An address | https, or a path on this site. Plain http from anywhere else is refused and does not load. A path on this site other than a built-in’s loads, but stays on its own device. |
| What a plugin keeps for itself | Its own localStorage, which never travels. |