Plugin Development: Getting Started
StudioBrain plugins extend the application with custom UI panels, backend logic, and entity processing. Starting with the 2026-04 release, plugins are built as WebAssembly (WASM) modules that run on all platforms: web, desktop, and mobile.
Why WASM?
| Benefit | Details |
|---|---|
| Cross-platform | One plugin binary runs on web (browser WASM), desktop (wasmtime), and mobile |
| Sandboxed | Plugins run in a memory-safe sandbox with no access to the host filesystem or network unless explicitly granted |
| Fast | Near-native performance for compute-heavy operations (search, analysis, transformation) |
| Language-agnostic | Write plugins in Rust, Python, TypeScript, C/C++, Go, or any language that compiles to WASM |
Plugin Capabilities
A StudioBrain plugin can do any combination of the following:
- Frontend panels — Custom UI rendered in the entity editor sidebar, as a tab, or as a full page
- Backend routes — Custom REST API endpoints under
/api/plugins/{plugin-id}/ - Event handlers — React to entity lifecycle events (created, updated, deleted)
- Settings — Global (admin) and per-user configuration
- Data storage — Persist plugin-specific data via the Plugin Data API
Quick Start
1. Scaffold a Plugin
Use the StudioBrain CLI to scaffold a new plugin project:
npx @biloxistudios/create-plugin my-plugin
cd my-pluginThis creates a project with:
my-plugin/
plugin.json # Plugin manifest (required)
src/
lib.rs # WASM module entry point (Rust template)
panels/
main-panel.html # Frontend panel
Cargo.toml # Rust build config
README.mdTemplates are available for Rust, Python (via componentize-py), and TypeScript (via javy).
2. Define the Manifest
Edit plugin.json to declare your plugin’s capabilities:
{
"id": "my-plugin",
"name": "My Plugin",
"version": "1.0.0",
"description": "A custom StudioBrain plugin",
"author": "Your Name",
"license": "MIT",
"icon": "Puzzle",
"wasm": {
"module": "target/wasm32-wasi/release/my_plugin.wasm"
},
"capabilities": {
"frontend": {
"panels": [
{
"id": "main-panel",
"title": "My Panel",
"location": "entity-sidebar",
"url": "/panels/main-panel.html"
}
]
},
"host_functions": [
"entity_read",
"entity_list",
"storage_get",
"storage_set"
],
"settings": {
"global": [
{
"key": "api_key",
"label": "External API Key",
"type": "password",
"default": ""
}
]
}
}
}3. Implement the WASM Module
For a Rust plugin:
// src/lib.rs
use studiobrain_plugin_sdk::*;
#[export]
fn on_entity_created(entity: Entity) -> Result<(), PluginError> {
let entity_type = entity.entity_type();
let entity_id = entity.id();
// Call a host function to read related entities
let related = host::entity_list(&format!(
"entity_type=character&related_to={}", entity_id
))?;
// Process and store results
host::storage_set(
&format!("analysis/{}", entity_id),
&serde_json::to_string(&related)?
)?;
Ok(())
}
#[export]
fn on_entity_updated(entity: Entity) -> Result<(), PluginError> {
// Re-run analysis on update
on_entity_created(entity)
}4. Build
# Rust
cargo build --target wasm32-wasi --release
# Python (via componentize-py)
componentize-py -d plugin.wit -w plugin componentize my_plugin -o my_plugin.wasm
# TypeScript (via javy)
javy compile src/index.js -o my_plugin.wasm5. Install
Copy the plugin directory to _Plugins/my-plugin/ in your StudioBrain project, or upload via the Plugin Marketplace UI in Settings.
Host Functions Reference
WASM plugins interact with StudioBrain through host functions — APIs that the host runtime makes available to the sandboxed module. Plugins declare which host functions they need in plugin.json under capabilities.host_functions.
| Host Function | Description | Parameters |
|---|---|---|
entity_read | Read a single entity by ID | (entity_type: string, entity_id: string) -> Entity |
entity_list | List entities with optional filters | (query: string) -> Entity[] |
entity_create | Create a new entity | (entity_type: string, data: string) -> Entity |
entity_update | Update an existing entity | (entity_type: string, entity_id: string, data: string) -> Entity |
entity_delete | Delete an entity | (entity_type: string, entity_id: string) -> bool |
storage_get | Read plugin-scoped data | (key: string) -> string |
storage_set | Write plugin-scoped data | (key: string, value: string) -> bool |
storage_delete | Delete plugin-scoped data | (key: string) -> bool |
storage_list | List keys in plugin storage | (prefix: string) -> string[] |
setting_get | Read a plugin setting value | (key: string) -> string |
log | Write to the plugin log | (level: string, message: string) -> void |
http_request | Make an outbound HTTP request (if permitted) | (method: string, url: string, body: string) -> Response |
Permission Model
Plugins only have access to the host functions they declare. Undeclared functions return an error at runtime. The http_request function requires explicit user approval during plugin installation.
Frontend Panels
Plugin frontend panels are HTML/CSS/JS files served in sandboxed iframes. They communicate with the host app via the postMessage protocol.
Iframe Protocol
The host sends these messages to the plugin iframe:
| Message Type | When | Data |
|---|---|---|
entity-context | On iframe load | Entity type, ID, data, theme |
entity-updated | When entity data changes | Updated entity data |
theme-change | When user toggles light/dark | Current theme |
The plugin can send these messages to the host:
| Message Type | Purpose | Data |
|---|---|---|
entity-modified | Request field updates | Changed fields |
navigate | Navigate host to a route | Path |
toast | Show notification | Message + level |
resize | Resize iframe container | Height in pixels |
See Plugin Iframe Protocol for full type definitions and examples.
Theme Compliance
Plugins must use CSS custom properties for colors, not hardcoded values. StudioBrain injects the current theme (light/dark) via the entity-context message. See Plugin Development for the surface variable reference.
SDK Templates
Starter templates are available for the three most common plugin languages:
| Language | Template | Build Tool |
|---|---|---|
| Rust | npx @biloxistudios/create-plugin --template rust | cargo build --target wasm32-wasi |
| Python | npx @biloxistudios/create-plugin --template python | componentize-py |
| TypeScript | npx @biloxistudios/create-plugin --template typescript | javy compile |
Each template includes a working plugin.json, a minimal WASM module, a frontend panel, and a build script.
Next Steps
- Plugin Examples — Walkthroughs of complete plugins
- Migrating from Python to WASM — Step-by-step migration guide
- Plugin Iframe Protocol — Full protocol reference
- Plugin Marketplace — Publishing and distributing plugins