Dynamic UI SDK
When you write a CUSTOM, FORM, or PDF_DOCUMENT codeblock,
you use the Dynamic UI SDK. The SDK runs inside the QuickJS sandbox and returns a
serialized TreeNode config that the frontend renderer consumes directly.
Authoring Pattern
Every UI codeblock exports run() and returns SDK.GlobalStore(...).
import { Params, ReturnType } from './data';
import { SDK } from './external';
export function run(params: Params): ReturnType {
return SDK.GlobalStore({
form_for: 'projects',
data: {
form: {
name: '',
status: 'active'
}
},
ui: (store) => (
<flex direction="column" gap={3}>
<forminput label="Name" value={store.bind('form.name')} type={{ render: 'text' }} />
</flex>
)
});
} Store API
The store object supports four core patterns:
store.bind(path)store.read(path)store.read(expr, { mode: 'CEL' })store.derive(pointer, expression)
CEL in Dynamic UI
Use CEL for:
- Visibility
- Dynamic props
- Derived values
pre_queryvalues that depend on current scope
Validation Behavior
Dynamic UI CEL is validated before render, including boolean visibility checks, string output
checks, and type-aware store.derive(...) validation.
Components
Dynamic UI includes layout, form, data, structure, and PDF components. Common examples include Flex, Text, FormInput, DataGrid, CollectionTable, TaskBlock, and Tabs.