Skip to content

Plugins

Bubbledesk’s Plugins provides a secure, sandboxed and flexible runtime for executing WebAssembly (WASM) plugins within the desktop wrapper.
This allows developers to extend app capabilities and Bubbledesk to release features without forcing new builds.

Overview

Each worker runs in its own hidden webview window (bd-worker) and executes WASM modules inside a Web Worker environment. The runtime isolates every execution, providing:

  • File system sandboxing
  • Automatic timeout and queue limits
  • JSON-based communication
  • Cross-platform consistency (macOS, Windows, Linux)

BRIDGE

Workers are managed via the JavaScript bridge at Bubbledesk.worker.

You can find the documentation for the worker module here.

Architecture

The system is composed of three layers:

LayerLanguageResponsibility
FrontendJavaScript or TypeScriptProvides the API under Bubbledesk.worker
Backend HostRust + TauriManages worker lifecycle, WASM validation, job queueing, and communication
Execution Layer (Web Worker)JavaScript + WASMExecutes the loaded WebAssembly module and streams stdout/stderr

All communication between host and worker is event-driven via the Tauri IPC system.

Input/Output Standard

The communication protocol is line-delimited JSON:

Input (from host → plugin)

The Bubbledesk sandbox passes JSON via stdin.

Example:

json
{ "fn": "add", "args": [3, 5] }

Output (from plugin → host)

The plugin must write a single line of JSON to stdout, terminated by \n.

Example:

Success:

json
{"ok": true, "value": 8}

Error:

json
{"ok": false, "error": "division by zero"}

This format is mandatory — the worker will reject malformed or multiline JSON.

Security and Sandbox

  • Each plugin executes in its own isolated environment.

    Each job runs in a sandboxed folder (/_sandbox/<jobId>), mapped as / inside the module. Here (and here only) you can read/write files with the plugin.

  • No network access or external FS access is allowed.
  • Max 64 concurrent pending jobs.
  • Input limited to 1 MB per call.
  • WASM modules must start with the standard \0asm magic bytes.

WASM Plugin Structure

Each plugin is an independent Rust project compiled for the wasm32-wasip1 target and executed as a WASI-compatible process.

Example structure:

math/
 ├─dist/
 |   └─ math.wasm
 ├─ src/
 │   ├─ main.rs
 │   ├─ dispatcher.rs
 │   └─ functions.rs
 ├─ Cargo.toml
 └─ package.json

Plugins communicate with the host via stdin/stdout, using a strict JSON protocol.

Requirements

  • Rust with WASI target:

    bash
    rustup target add wasm32-wasi
  • Node.js (for the build JS script build.js).

Build

Each module is built into .wasm with:

bash
npm run build -- <moduleDirName>

Example:

bash
npm run build -- math

Result in dist/ folder, example:

dist/math.wasm

Directory Layout

DirectoryPurpose
/_external_modules/Holds installed WASM modules
/_sandbox/<jobId>Temporary runtime area, wiped at startup

Develop a Plugin

  1. Fork the bd-wasm-module-template repo from Bubbledesk's GitHub:

    url
    https://github.com/Bubbledesk/bd-wasm-module-template
  2. Copy the module-template folder with a new name:

    bash
    cp -r module-template my-new-module
  3. Edit Cargo.toml with the module name and description.

  4. Implement your functions in functions.rs and register them in dispatcher.rs.

  5. Build:

    bash
    npm run build -- my-new-module
  6. You can load dist/my-new-module.wasm into your Bubbledesk app with:

    ts
    await Bubbledesk.worker.modules.add("moduleName");

    then select dist/my-new-module.wasm.

  7. You can list loaded modules with:

    ts
    await Bubbledesk.worker.modules.list();
  8. You can call it like this:

    js
    const res = await Bubbledesk.worker.call("moduleName.wasm", {
        fn: "function_name",
        args: [...]
    });
    
    console.log(JSON.parse(res).value);

Keywords References

  • Plugin = WASM Module
  • Worker = Isolated runtime where the plugins run
  • WASM = WebAssembly

WebAssembly (WASM)

WebAssembly (WASM) is a portable binary format that enables high-performance code — written in languages (like Rust, C, or C++) — to run safely inside browsers or sandboxed runtimes such as Tauri + browser web worker.

Notes

BRIDGE

Workers are managed via the JavaScript bridge at Bubbledesk.worker.

You can find the documentation for the worker module here.

NOTES

  • Keep functions pure and deterministic, without external side effects.
  • Do not use network: it is blocked by the sandbox.
  • Avoid extra stdout/stderr: only the final JSON output should be printed.
  • All modules must follow the stdin/stdout JSON protocol strictly. Multi-line, non-JSON, or binary outputs will be discarded.

WARNING

Avoid infinite loops or blocking operations inside your WASM module — they will trigger a timeout and the worker will be restarted.

All rights reserved.