outl docs
Confetti
Capability:
ui-render(+op-hook) · Source on GitHub
Throws a confetti burst every time you mark a block DONE.
What it demonstrates
ui-render lets a plugin hand a GUI client a chunk of author-written HTML/JS that it runs in a sandboxed iframe overlay.
The host knows nothing about “confetti” — the plugin produces the markup, the client only runs it (isolated, sandbox="allow-scripts" with no same-origin).
Want fireworks instead?
Rewrite CONFETTI_HTML — it’s your creativity, not a fixed catalog of effects.
It also shows op-hook: the burst is triggered from ctx.ops.onOp, watching for a block that transitions into DONE.
On the TUI/CLI the render is dropped (no webview); the op-hook still fires.
The code
import { definePlugin, type LogOp, type PluginContext } from "@outl/plugin-sdk";
const CONFETTI_HTML = `<!doctype html>... a full-screen <canvas> + a tiny
particle simulation, fully inline (the iframe has no network, no imports) ...`;
export default definePlugin({
activate(ctx: PluginContext) {
ctx.ops.onOp((op: LogOp) => {
// A TODO→DONE toggle lands as an `Edit` op the host projects `todo: "DONE"` onto.
if (op.kind === "Edit" && op.todo === "DONE") {
ctx.ui.render(CONFETTI_HTML);
}
});
},
});
See src/index.ts for the full CONFETTI_HTML.
Manifest
"capabilities": ["op-hook", "ui-render"],
"permissions": ["read-op-log"]
Try it
outl -w <workspace> plugin install ./examples/confetti --yes
Open the workspace in the desktop or mobile app, mark any block DONE (Cmd+T) → 🎉.
Adapting it
ctx.ui.render(html) runs whatever HTML/JS you give it in an isolated iframe.
Swap CONFETTI_HTML for any self-contained visual — a toast, an SVG badge, a celebratory GIF — and trigger it from any hook or command.
Keep it inline: the sandbox has no network and no imports.