A working template for building Froots community plugins. Use this repo as your starting point ("Use this template" on GitHub, or just copy the folder).
Three files in a folder — no build step required:
sample-plugin/
├── manifest.json id, name, version, minAppVersion, description, author
├── main.js plain ES module: export default { onload(app), onunload() }
└── styles.css optional CSS, injected while enabled
The app argument to onload is the Froots plugin API (typed by
froots.d.ts, published as
froots-api). Everything you
register through it — commands, event listeners, intervals, DOM handlers — is
automatically cleaned up when your plugin is disabled.
This sample exercises the whole API surface in ~120 lines — read
main.js:
- A viewport tab ("Sample Board", kanban icon) registered via
app.ui.registerView— your own top-level surface next to Files / Dev / Inbox, with a working button that calls back into the KB API. Passtab: falseto make a view ⌘K-only instead (no tab-strip presence). - Three ⌘K commands ("Count KB notes", "Say hello", "Open Sample Board" —
the latter jumps to the view via
app.ui.openView). - A run counter persisted to
data.json, an app-event subscription, and a heartbeat interval — all auto-cleaned on disable.
Requires Froots 0.1.17+ for the view API (minAppVersion handles this —
older apps are offered v1.0.0, the commands-only release, via
versions.json).
- Never develop against a workspace you care about — dev builds of Froots use a separate data dir, use that.
- Copy this folder to
<app data>/workspace/plugins/sample-plugin/(Settings → Plugins → "Open plugins folder" takes you there). - In Froots: Settings → Plugins → turn on community plugins (they're off by default; plugins run unsandboxed code — the gate is explicit) → toggle your plugin on.
- Edit
main.js→ Reload plugins → your changes are live. The dev folder is the install folder.
Rename id in manifest.json (lowercase letters/digits/hyphens; must match
the folder name) before publishing.
Write main.ts importing types from froots-api and bundle to main.js
with esbuild (format: "esm", bundle: true). Since the API arrives as an
argument — not an import — there are no externals to configure. Plain JS with
// @ts-check (as this template does) gets you the same editor safety with
zero tooling.
- Bump
versioninmanifest.json, add the entry toversions.json("<plugin version>": "<min app version>"). - Create a GitHub release whose tag exactly equals the manifest version
(no
vprefix). - Attach
manifest.json,main.js, andstyles.cssas individual release assets.
Users install by dropping those files in a folder under
workspace/plugins/ — and once the Froots community registry opens,
you'll submit {id, name, author, description, repo} there and installs
happen in-app, with GitHub Releases as the CDN.