CONTRIBUTOR GUIDE · CLIENT-SIDE · NO BUILD STEP

Build a tool for PolyPotion

A tool is just an HTML page. The shell mounts it in an iframe, and the two talk over a small set of postMessage events — every one tagged { __studio: true }. Learn these events and your tool joins the dock, receives the active character, and hands results to the rest of the pipeline. No framework, no bundler, no server.

1 · It's your page
Any HTML/JS/WebGL. The shell never reaches inside — it only sends and receives messages.
2 · One handshake
Post studio:ready once you can accept a mesh. The shell flushes whatever was queued for you.
3 · Characters flow
Receive the active character; hand your result on with saveChar or routeBuffer.

The iframe lifecycle

  1. The shell lazily creates <iframe src="YourTool.dc.html?embed=1"> the first time the user opens your tool.
  2. Your page boots. Detect embedding with window.parent !== window (or the ?embed=1 flag) and hide your own top-bar chrome so it sits flush in the shell.
  3. When your engine is ready to accept a mesh, post studio:ready. The shell hides your loader and flushes any pending character delivery.
  4. The shell may deliver the active character more than once (first visit, and again if your frame was reclaimed to save GPU memory). Handle every loadChar* idempotently.
  5. Idle, off-screen frames can be evicted (WebGL contexts are capped). Keep important state in messages you've sent back, not only in the frame — the shell re-delivers the active character on reopen.

Messages the shell sends you

Listen on window; ignore anything without __studio.

Messages you send the shell

window.parent.postMessage(msg, '*', transfer) — pass big ArrayBuffers in the transfer list so they move, not copy.

Hello Tool — copy, paste, ship

The smallest complete tool: it handshakes, receives a character, and can hand a result back. Save as HelloTool.dc.html.


    

Register it in the shell

Four small edits in index.html and your tool is in the dock, the command palette, and the character flow.


      

Add your tool's filename to the CORE list in sw.js too, so it's precached for offline use.

Rules & good manners

Speak GLB
Accept and emit binary glTF (.glb) as ArrayBuffers — the shell's lingua franca. Parse with three's GLTFLoader.
Transfer, don't copy
Put buffers in the transfer list. A 40 MB character copied per hop adds up fast.
Stay local
No uploads. Anything networked (an AI helper, a CDN model) must be opt-in and clearly labelled — it's the promise users came for.
Follow the theme
Load theme.js and use its CSS variables so your tool restyles with the rest.
Report errors
Send studio:error so the shell can surface a toast instead of failing silently.
Survive re-delivery
Loading the same character twice must be safe — clear your scene first.