Project Structure
A Lumio extension project has this layout:
my-extension/
+-- lumio.config.json <- Extension manifest (required)
+-- package.json <- Dependencies: @zaflun/lumio-sdk + react
+-- tsconfig.json <- TypeScript config
+-- CHANGELOG.md <- Release notes (optional, recommended)
+-- src/
| +-- editor.tsx <- Dashboard panel (sidebar in overlay editor)
| +-- layer.tsx <- OBS overlay surface (transparent)
| +-- interactive.tsx <- Audience page (optional)
+-- server/ <- Optional (server: true in config)
+-- schema.ts <- DB schema (defineTable with validators)
+-- functions.ts <- Server functions (query/mutation/action)
lumio.config.json
The manifest file that defines your extension. See Configuration for all fields.
{
"$schema": "https://docs.lumio.vision/schemas/lumio.config.schema.json",
"extensionId": "88b2478a-39c7-468e-bebd-14e52fd97ac0",
"name": "My Extension",
"description": "What this extension does",
"category": "widget",
"version": "1.0.0",
"targets": ["editor", "layer"],
"server": false,
"permissions": [],
"visibility": "private",
"pricing": {
"type": "free"
}
}
The extensionId is generated when you run lumio init or create the extension in the dashboard. It must be a valid UUID that exists in the Lumio database.
src/editor.tsx
The editor surface renders in the dashboard overlay editor sidebar. This is where users configure your extension. Every editor file must call Lumio.render() within 10 seconds of page load.
src/layer.tsx
The layer surface renders in OBS Browser Sources as a transparent overlay. Input components (buttons, toggles, text fields) are automatically read-only on this surface.
src/interactive.tsx
The interactive surface renders on a standalone page at /ext/\{slug\}. Viewers can interact with it directly (voting, playing games). This surface is optional.
server/schema.ts
Defines database tables for your extension using defineSchema and defineTable. Each table gets isolated storage in ext_\{extension_id\}.* PostgreSQL schemas.
server/functions.ts
Defines server functions that run on the Lumio API. Declarative functions (queryRows, insertRow, patchRow, deleteRow) transpile to SQL. Handler-based functions (query(), mutation(), action()) run in a V8 sandbox.
CHANGELOG.md
Optional (recommended). If present, should follow the Keep a Changelog format. lumio deploy reads the entry for the deployed version and uses it as a fallback for release notes. The primary way to write release notes is the dashboard submission wizard.