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:

  1. store.bind(path)
  2. store.read(path)
  3. store.read(expr, { mode: 'CEL' })
  4. store.derive(pointer, expression)

CEL in Dynamic UI

Use CEL for:

  • Visibility
  • Dynamic props
  • Derived values
  • pre_query values 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.