Plugin Development: Getting Started
StudioBrain plugins extend the app with sandboxed backend logic and HTML panels. Official and community code is a WIT Component (Rust → cargo component) that desktop and mobile run in wasmtime. Official cloud plugins are a Worker per plugin, compiled at Biloxi deploy. Community plugins never run as Workers on BiloxiStudios Cloudflare.
Read the lock first: Plugin Architecture.
Where does it run?
| Kind | Desktop | Mobile | Cloud |
|---|---|---|---|
| Official universal | Component (wasmtime Cranelift) | Same Component (wasmtime Pulley, SBAI-7745) | Official Worker at our deploy. Panels everywhere. |
| Official desktop-only | Component + network:local + environments: ["desktop"] | — | — |
| Community plugin | Component | Same Component | Panel iframe and/or the author’s backend |
| Any data kind | Files in the project | Files in the project | Files in the project. No Worker. |
Why a Component (and not “one WASM for the web”)
- Desktop loads the Component with wasmtime Cranelift.
- Mobile loads the same Component with wasmtime Pulley (SBAI-7745). Not wasmi.
- Cloud cannot
WebAssembly.compilefetched R2 bytes. Official plugins that need a guest on cloud ship as a Worker we compile at deploy. Experimental WASI-on-Workers is not the StudioBrain WIT world. - Panels (static HTML/JS) run on every surface in a sandboxed iframe.
What you can build
- Frontend panels — entity sidebar, tab, or standalone page
- Host hooks — validate, react to create/update/delete
- Plugin-scoped storage — via the Plugin Data API
- Settings — global (admin) and per-user
- Official cloud routes — only on an official Worker we deploy
- Community cloud server — the author’s own backend, not ours
Official proofs
Start from the Rust proofs in studiobrain-plugins:
| Plugin | Why copy it |
|---|---|
| entity-notes | Panel + plugin-data + a host-entities hook |
| entity-snapshots | Save-hook snapshots + history panel |
| content-stats | Read-only stats from the Component |
Follow-on samples (Track H tickets, not proofs): hello-world, webhook-automations, pdf-exporter, comparison, kanban-board, google-sheets-sync, assembly-composer, blender-bridge.
prompt-engine is not a plugin. Core owns it.
Quick start (community or local)
1. Copy a proof, do not invent a new home
Official/vendor code lives in studiobrain-plugins. Community listings go to studiobrain-community (today studiobrain-community-plugins) on the plugins index. Official data (templates, rules, skills, layouts) stays in studiobrain-templates — that repo is not a plugin home.
my-plugin/
plugin.json # Manifest (required)
src/lib.rs # WIT Component guest (Rust)
Cargo.toml # cargo-component, StudioBrain plugin world
frontend/
panel.html # Sandboxed iframe panel
README.md2. Manifest
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "A custom StudioBrain plugin",
"author": "Your Name",
"license": "Apache-2.0",
"trust_tier": "community",
"type": "full",
"capabilities": {
"backend": {
"entry": "plugin.wasm"
},
"frontend": {
"panels": [
{
"id": "main-panel",
"title": "My Panel",
"location": "entity-sidebar"
}
]
}
},
"permissions": ["read_entities"]
}Declare only the host capabilities you need. network:local is official desktop-only and is rejected for community plugins.
3. Implement the Component
// src/lib.rs — cargo-component guest against the StudioBrain plugin WIT world
// See first-party/entity-notes in studiobrain-plugins for a complete hook.
fn on_entity_validate(/* entity from host */) -> Result<(), String> {
// Call host-entities / plugin storage through WIT imports.
Ok(())
}Build:
cargo install cargo-component wasm-tools
cargo component build --release
# copy the wasm32-wasip1 release Component to plugin.wasmDo not target a raw wasm32-wasi core module and expect the host to load it. The host wants a Component for the StudioBrain WIT world.
Python componentize-py and Javy one-offs are not the official proof path. Proofs are Rust Components. Community plugins that compile to the same WIT world can use other languages; they still do not become Workers on our Cloudflare account.
4. Install (per-project)
Marketplace is the only store UI: Settings → Plugins → Marketplace.
- Pick a project. Install is per-project, not tenant-wide.
- Tenant policy is an allowlist. If the plugin ID is not allowed, Marketplace will not install it.
- Desktop / mobile: Marketplace fetches the Component + panels, verifies the listing, writes them into the project plugin dir, wasmtime loads the Component.
- Cloud (community): panels load in an iframe. Backend logic, if any, is the author’s server. We do not compile or load your WASM as a Worker.
- Cloud (official): we already deployed that plugin’s Worker; enable it for the project.
For local iteration, copy the plugin directory into the project’s plugin folder and enable it for that project. Git-clone install and zip upload are development conveniences, not a second store.
5. Enable
After install, enable the plugin on that project (Settings → Plugins, or the project plugin API). Capability consent still applies for community plugins.
Host functions
The Component talks to StudioBrain only through WIT imports the host implements. Typical groups: entities, plugin storage, settings, log/notify, mediated HTTP, AI generate. See Host Functions and Permissions.
Undeclared functions fail at runtime. http_request and write capabilities require consent. network:local never appears on cloud.
Frontend panels
Panels are HTML/CSS/JS in sandboxed iframes. They use the postMessage protocol (entity-context, entity-updated, theme-change, entity-modified, toast, resize). See Plugin Iframe Protocol.
Use semantic surface CSS variables. Hardcoded colors break user themes — Plugin Development.
Next steps
- Architecture — repos, runtimes, what 2026-08-14 got wrong
- Creating Plugins — full manifest and official vs community
- Examples — official proofs
- Community submissions — plugins index vs catalog-data index
- Marketplace — browse, allowlist, per-project install