Quickstart
Build and run your first Lumio extension in 5 minutes.
1. Install the CLI
npm install -g @zaflun/lumio-cli
2. Log in to Lumio
lumio login
This opens your browser for PKCE OAuth authentication. After login, credentials are stored in ~/.lumio/credentials.
For CI/CD environments, use token-based auth:
lumio login --token lm_usr_your_api_key_here
3. Scaffold a new extension
lumio init my-first-extension
The interactive wizard asks:
? Extension name: My First Extension
? Description: A hello world extension
? Category: widget
? Targets: editor, layer
? Server functions: no
This creates the extension on Lumio (generating an Extension-ID), scaffolds the project, and writes lumio.config.json.
4. Set up AI assistant (optional)
If you use an AI coding assistant (Claude Code, Copilot, Cursor, Gemini, Windsurf, Codex), install the Lumio skill files so your assistant understands the SDK:
npx @zaflun/lumio-agent-skill add
This creates .lumio/skills/ with reference docs that teach your assistant about components, hooks, server functions, and CLI commands. See AI Assistant Integration for per-tool setup.
5. Start the dev server
cd my-first-extension
pnpm install
lumio dev
This starts a Vite dev server with hot-reload and a Lumio sandbox that simulates the host environment with mock events.
6. Edit the extension
Open src/editor.tsx:
import { Lumio, CompactView, TextField, Toggle, useExtensionStorage } from "@zaflun/lumio-sdk";
function Settings() {
const [storage, setStorage] = useExtensionStorage();
return (
<CompactView title="My First Extension">
<Toggle
label="Visible"
checked={storage.visible ?? false}
onChange={(checked) => setStorage({ ...storage, visible: checked })}
/>
<TextField
label="Message"
value={storage.text ?? ""}
onChange={(value) => setStorage({ ...storage, text: value })}
/>
</CompactView>
);
}
Lumio.render(<Settings />, { target: "editor" });
Open src/layer.tsx:
import { Lumio, Text, useExtensionStorage } from "@zaflun/lumio-sdk";
function Overlay() {
const [storage] = useExtensionStorage();
if (!storage.visible) return null;
return <Text content={storage.text ?? "Hello World"} variant="heading" />;
}
Lumio.render(<Overlay />, { target: "layer" });
Changes in the editor surface propagate to the layer in real time.
7. Build and deploy
lumio build
lumio deploy -v 1.0.0 -d "Initial release"
Your extension is now uploaded as a draft. Use the submission wizard in the dashboard to submit it for review.
Next steps
- Project structure — understand every file
- Surfaces — learn about the three rendering targets
- SDK hooks — all available hooks and components
- Server functions — add data persistence