Optional/community modules for theprototype.app — one
monorepo, one module per folder under modules/, each versioned independently of
app releases via its manifest.json. Core modules that ship in the app bundle
live in the main repo (theprototype-app/core, src/modules/); this repo is for
everything installable through Modules ▸ Install (zip upload or URL).
Writing one? AUTHORING.md is the single entry point — the rules, the API digest and the testing recipe. Known SDK gaps are tracked in DEVX-REQUESTS.md.
npm install
npm run new -- my-module "My Module" # scaffold from modules/_template
npm run pack -- my-module # -> my-module.zip, ready to installA module is a folder with:
manifest.json—{ id, name, version, format, description, entry, files }(entrydefaults tomodule.js)module.js— self-contained (noimportstatements; everything comes from theapiargument):export default { id, name, version, description, register(api) }
Full contract: AUTHORING.md §2–§3 and the docs site's
module-package page. The api
surface is documented in the core repo's MODULES.md and on the docs site's
module-sdk page.
npm run pack -- <id> writes <id>.zip with manifest.json at the zip root
(what the manager expects) and refuses a module with a top-level import:
npm run pack -- door-keypad # one
npm run pack -- --all # every moduleDo not use Compress-Archive on the folder — it nests the directory inside
the zip and the manager rejects it with "zip has no manifest.json at its root".
Then in the app: burger menu ▸ Modules ▸ User ▸ Install from zip (or serve the folder and install by URL).
Each peer installs modules themselves. What actually crosses the wire is:
- the
{id, version}list of loaded modules, exchanged on connect — a mismatch (missing module, or a different version) raises a toast on both sides and nothing else; - your module's own
api.send()messages, and itsregisterStateSyncstate for late joiners.
The module's code and assets never travel. A peer without the module simply
drops its messages, and only sees whatever plain scene objects it created
through /create. Share the zip (or a URL) with the people you session with.
Every module ships a Playwright test-flight that installs the real zip through the real manager and drives the app — see tests/README.md.
npx playwright install chromium # once
npm run pack -- --all
APP_URL=https://localhost:5188/ npm test- Install the zip, create a Box.
- Select the Box → Flow editor shows "Box has no flow yet" → Create flow.
- Add Wobble (toolkit) from the palette's Custom section — the Box wobbles (no Object Selector needed inside an object flow).
- Open the def in the Node Designer and edit the formula — your edit sticks.
- Add a Flow Input named
amount(number) wired into a Breathe node'samount, then right-click the Box → Add flow to Scene graph — the Scene graph gets an Object Flow node whoseamountsocket drives the breathing.
- Bump a module's
manifest.jsonversion per change; the app toasts on version mismatches between peers. - When the main repo's module SDK changes shape, this repo's modules are updated
in the same sitting (see the maintenance contract in the cloud repo's
MAINTAINING.md — same principle: the
apisurface is the API).
