Beta: needs approval. Mods are in beta. You can build and test a mod today; to install one on a Lucra account, ask Lucra for access.
Scaffold
npm install -g @lucra/mod
curl -O https://www.onlucra.com/docs/mods/ui.json
mod init my-mod --id acme.notes --ui ui.json
ui.json is Lucra's contract: every component a mod can use, every slot, the events Lucra sends and its theme. mod init aims the mod at Lucra and writes llms.txt, a Claude skill and AGENTS.md, so a coding agent writes valid mods first time.
Write it
import { defineMod, serve } from "@lucra/mod/server"
export default serve(defineMod({
render: {
notes: () => ({ type: "Section", props: { title: "Notes" }, children: [
{ type: "TextField", props: { label: "Note", name: "note" } },
{ type: "Button", props: { label: "Save", action: "save" } },
] }),
},
actions: {
save: ({ input }) => ({ effects: [{ type: "toast", message: `Saved: ${String(input?.note ?? "")}` }] }),
},
}))
mod.json says what the mod is: its ID and name, the permissions its install asks for (read, write), where it shows (contributes), and the only hosts its server may reach (network.allow).
Check it
| Command | |
|---|---|
mod render mod.json nav.page notes --ui ui.json | Run it locally and validate what it draws. Add --action save to run an action. |
mod manifest mod.json --ui ui.json | Check mod.json fits Lucra. |
mod dev mod.json --ui ui.json | Serve it over the real signed protocol, rebuilding on save. |
mod build mod.json | Bundle it for deployment. It refuses code that runs strings as code. |
mod conformance mod.json --ui ui.json --url … --secret … | Check a deployment refuses unsigned calls and answers correctly. |
Ship it
Deploy the build anywhere that runs JavaScript, then ask Lucra to install it on your account. Once it's installed, it shows in Settings → Developers → Mods and its pages appear under Mods in the sidebar.