A module is one manifest, a sandboxed UI, and a permissioned bridge to the desktop. Build a small app, publish it to the Module Store, and it runs in every user's window. No prior experience assumed.
Starter manifest, a UI shell and a sample input.
The same rules the backend runs on upload.
A safety-scanned, upload-ready zip.
Upload, admin review, then the Module Store.
Your UI reaches the desktop only through declared, scoped capabilities — the SDK turns that protocol into plain await calls. Tap one:
const hanabi = createHanabiClient();
const ctx = await hanabi.ready();
// → { user, theme, accent, windowId } The platform ships continuously. Here's the latest, plus where the roadmap stands.
One module can now call a named service another installed module exposes; it runs as a sandboxed job under the provider's grants.
Modules can now receive external HTTP events through registered webhook endpoints, each with its own rotatable secret.
The platform now serves several versions of a module at once, with stable and beta channels and canary rollout to a slice of users.
Your UI runs in an opaque-origin iframe and reaches the platform only through the capability bridge — every
call declared, granted, and scoped. The SDK turns that protocol into plain await calls.
import { createHanabiClient } from '@hanabi/module-sdk'; const hanabi = createHanabiClient(); const ctx = await hanabi.ready(); // read context const { files } = await hanabi.pickFile(['xlsx']); // files.read const file = await hanabi.readFile(files[0].id); // file.bytesB64 await hanabi.writeFile('result.csv', out); // files.write