useLumioConfig
Read and write the extension's user-configurable settings as defined in config_schema in lumio.config.json. Config values are persisted per installation and displayed in a dedicated settings UI separate from the main editor panel.
Signature
const [config, setConfig] = useLumioConfig();
Parameters
This hook takes no parameters.
Return value
Returns a tuple of two values:
| Index | Type | Description |
|---|---|---|
0 | LumioConfig | The install's config (see below) |
1 | (config: LumioConfig | (prev: LumioConfig) => LumioConfig) => void | Setter -- accepts a new config object or a functional updater |
LumioConfig shape
interface LumioConfig {
extension_id?: string;
install_id?: string;
account_id?: string;
target?: "editor" | "layer";
permissions?: string[];
settings?: Record<string, unknown>; // the values of your config_schema fields
}
The values of your config_schema fields live in config.settings. The first render already has them: the host sends them in lifecycle.init, before your bundle runs. A config.update from the host replaces only the fields it carries (in practice settings); the install fields stay.
Example
Define the schema in lumio.config.json:
{
"config_schema": {
"primaryColor": {
"type": "string",
"label": "Primary color",
"default": "#6366f1"
},
"showAvatar": {
"type": "boolean",
"label": "Show avatar",
"default": true
},
"fontSize": {
"type": "number",
"label": "Font size (px)",
"default": 16
}
}
}
Then use it in any surface:
import { useLumioConfig, Text, Box } from "@zaflun/lumio-sdk";
interface MyConfig {
primaryColor: string;
showAvatar: boolean;
fontSize: number;
}
function AlertOverlay() {
const [config] = useLumioConfig();
const settings = config.settings as Partial<MyConfig> | undefined;
return (
<Box
style={{
background: settings?.primaryColor,
fontSize: settings?.fontSize,
}}
>
<Text content="New follower!" variant="heading" />
</Box>
);
}
Functional updater
The setter accepts a functional updater (prev) => next, which is the recommended pattern in editor.tsx to avoid overwriting concurrent changes:
import { useLumioConfig, EditorInput, EditorSlider } from "@zaflun/lumio-sdk";
function Settings() {
const [config, setConfig] = useLumioConfig();
// Functional updater -- recommended for editor.tsx
const update = (key: string, value: unknown) =>
setConfig((prev) => ({
...prev,
settings: { ...(prev.settings ?? {}), [key]: value },
}));
return (
<>
<EditorInput
label="Title"
value={String(config.settings?.title ?? "")}
onChange={(v) => update("title", v)}
/>
<EditorSlider
label="Opacity"
value={Number(config.settings?.opacity ?? 100)}
onChange={(v) => update("opacity", v)}
min={0}
max={100}
unit="%"
/>
</>
);
}
The functional form (prev) => next is safer than passing a full object because it reads the latest state at update time, preventing race conditions when multiple fields update in quick succession.
Difference from useExtensionStorage
useLumioConfig | useExtensionStorage | |
|---|---|---|
| Schema | Defined in config_schema (typed) | Untyped key-value |
| UI | Auto-generated settings panel | Custom editor panel in src/editor.tsx |
| Purpose | User-facing settings (theme, preferences) | Runtime state (scores, current topic) |
| Scope | Per installation | Per installation |
Notes
- The config values are initialized with defaults from
config_schemaon first install - Changes to config trigger a re-render on all surfaces that use
useLumioConfig() - Config is not intended for high-frequency updates (use
useExtensionStorage()for that) - The hook is not generic; cast
config.settingsto your own settings type - 17 field types are supported in
config_schema:string,number,boolean,color,select,textarea,slider,font,icon,image,sound,multiselect,group,divider,info,channel,designer- see lumio.config.json reference for details