Skip to content

App Builder Components

Complete reference for all App Builder components

Every component follows this structure:

{
"id": "unique-id",
"type": "component-type",
"visible": "{{ optional.expression }}",
"width": "auto",
"props": {
// Component-specific properties
}
}
PropertyTypeDescription
idstringUnique identifier within the page
typestringComponent type (see below)
visiblestringExpression that controls visibility
widthstringauto, full, 1/2, 1/3, 1/4, 2/3, 3/4
loadingWorkflowsstring[]Workflow IDs - shows skeleton while any are executing
propsobjectComponent-specific configuration

Horizontal flex container.

{
"type": "row",
"gap": 16,
"padding": 0,
"align": "center",
"justify": "between",
"children": []
}
PropertyTypeDefaultDescription
gapnumber0Space between children (pixels)
paddingnumber0Internal padding (pixels)
alignstringstretchstart, center, end, stretch
justifystringstartstart, center, end, between, around
childrenarray[]Nested layouts or components

Vertical flex container.

{
"type": "column",
"gap": 16,
"padding": 0,
"align": "stretch",
"children": []
}

Same properties as Row.

CSS grid container.

{
"type": "grid",
"columns": 3,
"gap": 16,
"padding": 0,
"children": []
}
PropertyTypeDefaultDescription
columnsnumber2Number of grid columns
gapnumber0Space between cells (pixels)
paddingnumber0Internal padding (pixels)
childrenarray[]Nested layouts or components

{
"type": "heading",
"props": {
"text": "Welcome, {{ user.name }}",
"level": 1,
"className": "text-blue-600"
}
}
PropertyTypeDefaultDescription
textstringrequiredHeading text (supports expressions)
levelnumber11-6, maps to h1-h6
classNamestring-Additional CSS classes
{
"type": "text",
"props": {
"text": "Total items: {{ data.items.length }}",
"label": "Summary",
"className": "text-muted-foreground"
}
}
PropertyTypeDefaultDescription
textstringrequiredText content (supports expressions)
labelstring-Optional label above text
classNamestring-Additional CSS classes

Renders sanitized HTML content.

{
"type": "html",
"props": {
"content": "<p>Custom <strong>formatted</strong> content</p>",
"className": "prose"
}
}
PropertyTypeDefaultDescription
contentstringrequiredHTML content (sanitized)
classNamestring-Additional CSS classes
{
"type": "badge",
"props": {
"text": "{{ row.status }}",
"variant": "default"
}
}
PropertyTypeDefaultDescription
textstringrequiredBadge text (supports expressions)
variantstringdefaultdefault, secondary, destructive, outline
classNamestring-Additional CSS classes
{
"type": "progress",
"props": {
"value": "{{ data.completion }}",
"showLabel": true
}
}
PropertyTypeDefaultDescription
valuenumber/stringrequired0-100 (supports expressions)
showLabelbooleanfalseShow percentage label
classNamestring-Additional CSS classes
{
"type": "image",
"props": {
"src": "{{ data.user.avatarUrl }}",
"alt": "User avatar",
"maxWidth": 200,
"maxHeight": 200,
"objectFit": "cover"
}
}
PropertyTypeDefaultDescription
srcstringrequiredImage URL (supports expressions)
altstring-Alt text for accessibility
maxWidthnumber/string-Maximum width
maxHeightnumber/string-Maximum height
objectFitstringcontaincontain, cover, fill, none
classNamestring-Additional CSS classes

Dashboard statistics card.

{
"type": "stat-card",
"loadingWorkflows": ["stats-workflow-id"],
"props": {
"title": "Total Revenue",
"value": "${{ data.stats.revenue }}",
"description": "This month",
"icon": "dollar-sign",
"trend": {
"value": "+12%",
"direction": "up"
},
"onClick": {
"type": "navigate",
"navigateTo": "/reports/revenue"
}
}
}
PropertyTypeDefaultDescription
titlestringrequiredCard title
valuestringrequiredMain value (supports expressions)
descriptionstring-Subtitle text
iconstring-Lucide icon name
trend.valuestring-Trend indicator text
trend.directionstring-up, down, neutral
onClickobject-Click action (navigate or workflow)
classNamestring-Additional CSS classes

Container with optional header.

{
"type": "card",
"props": {
"title": "User Details",
"description": "View and edit user information",
"children": []
}
}
PropertyTypeDefaultDescription
titlestring-Card header title
descriptionstring-Card header description
childrenarray[]Nested layouts/components
classNamestring-Additional CSS classes
{
"type": "divider",
"props": {
"orientation": "horizontal"
}
}
PropertyTypeDefaultDescription
orientationstringhorizontalhorizontal, vertical
classNamestring-Additional CSS classes
{
"type": "spacer",
"props": {
"size": 32
}
}
PropertyTypeDefaultDescription
sizenumber/string16Space size in pixels
classNamestring-Additional CSS classes

Full-featured data table with sorting, pagination, and actions.

{
"type": "data-table",
"props": {
"dataSource": "customers",
"cacheKey": "customers-table",
"columns": [
{ "key": "name", "header": "Name", "sortable": true },
{ "key": "email", "header": "Email" },
{
"key": "status",
"header": "Status",
"type": "badge",
"badgeColors": {
"active": "green",
"inactive": "gray",
"pending": "yellow"
}
},
{ "key": "createdAt", "header": "Created", "type": "date" }
],
"searchable": true,
"paginated": true,
"pageSize": 20,
"selectable": true,
"onRowClick": {
"type": "navigate",
"navigateTo": "/customers/{{ row.id }}"
},
"rowActions": [
{
"label": "",
"icon": "Eye",
"onClick": {
"type": "navigate",
"navigateTo": "/customers/{{ row.id }}"
}
},
{
"label": "Edit",
"icon": "Pencil",
"onClick": {
"type": "navigate",
"navigateTo": "/customers/{{ row.id }}/edit"
}
},
{
"label": "Delete",
"icon": "Trash",
"variant": "destructive",
"disabled": "{{ row.status == 'active' }}",
"onClick": {
"type": "workflow",
"workflowId": "delete_customer",
"actionParams": {
"customerId": "{{ row.id }}"
}
},
"confirm": {
"title": "Delete Customer",
"message": "Are you sure you want to delete {{ row.name }}?",
"confirmLabel": "Delete",
"cancelLabel": "Cancel"
}
}
],
"headerActions": [
{
"label": "Export",
"icon": "Download",
"onClick": {
"type": "workflow",
"workflowId": "export_customers"
}
}
],
"emptyMessage": "No customers found"
}
}
PropertyTypeDefaultDescription
cacheKeystring-Persist table data across page navigations (shows refresh button)
PropertyTypeDescription
keystringData field path (dot notation: user.name)
headerstringColumn header text
typestringtext, number, date, badge
widthnumber/stringColumn width
sortablebooleanEnable sorting
badgeColorsobjectMap values to colors (for badge type)
PropertyTypeDescription
labelstringAction button label (empty string + icon = icon-only button with tooltip)
iconstringLucide icon name (PascalCase, e.g., Eye, Pencil, Trash)
variantstringdefault, destructive, outline, ghost
visiblestringVisibility expression
disabledstringDisabled expression (e.g., {{ row.locked }})
onClickobjectAction configuration
confirmobjectConfirmation dialog

Tabbed content container.

{
"type": "tabs",
"props": {
"defaultTab": "overview",
"orientation": "horizontal",
"items": [
{
"id": "overview",
"label": "Overview",
"icon": "home",
"content": {
"type": "column",
"children": []
}
},
{
"id": "settings",
"label": "Settings",
"icon": "settings",
"content": {
"type": "column",
"children": []
}
}
]
}
}
PropertyTypeDescription
defaultTabstringID of initially active tab
orientationstringhorizontal, vertical
itemsarrayTab definitions
PropertyTypeDescription
idstringUnique tab identifier
labelstringTab button label
iconstringLucide icon name
contentobjectLayout container for tab content

Display files inline, in modal, or as download.

{
"type": "file-viewer",
"props": {
"src": "{{ data.document.url }}",
"fileName": "{{ data.document.name }}",
"mimeType": "application/pdf",
"displayMode": "inline",
"maxWidth": 800,
"maxHeight": 600,
"showDownloadButton": true
}
}
PropertyTypeDefaultDescription
srcstringrequiredFile URL (supports expressions)
fileNamestring-Display name for file
mimeTypestring-MIME type (auto-detected if omitted)
displayModestringinlineinline, modal, download
maxWidthnumber/string-Maximum display width
maxHeightnumber/string-Maximum display height
showDownloadButtonbooleantrueShow download button
downloadLabelstringDownloadDownload button text

Form inputs automatically register their values in the expression context under {{ field.fieldId }}.

{
"type": "text-input",
"props": {
"fieldId": "customerName",
"label": "Customer Name",
"placeholder": "Enter customer name",
"defaultValue": "{{ data.customer.name }}",
"required": true,
"disabled": "{{ !user.canEdit }}",
"inputType": "text",
"minLength": 2,
"maxLength": 100,
"pattern": "^[A-Za-z\\s]+$"
}
}
PropertyTypeDefaultDescription
fieldIdstringrequiredUnique field identifier
labelstring-Field label
placeholderstring-Placeholder text
defaultValuestring-Initial value (supports expressions)
requiredbooleanfalseField is required
disabledboolean/stringfalseDisable field (supports expressions)
inputTypestringtexttext, email, password, url, tel
minLengthnumber-Minimum character length
maxLengthnumber-Maximum character length
patternstring-Regex validation pattern
{
"type": "number-input",
"props": {
"fieldId": "quantity",
"label": "Quantity",
"placeholder": "0",
"defaultValue": 1,
"required": true,
"min": 1,
"max": 100,
"step": 1
}
}
PropertyTypeDefaultDescription
fieldIdstringrequiredUnique field identifier
labelstring-Field label
placeholderstring-Placeholder text
defaultValuenumber/string-Initial value
requiredbooleanfalseField is required
disabledboolean/stringfalseDisable field
minnumber-Minimum value
maxnumber-Maximum value
stepnumber1Increment step
{
"type": "select",
"props": {
"fieldId": "department",
"label": "Department",
"placeholder": "Select department",
"required": true,
"options": [
{ "label": "Engineering", "value": "eng" },
{ "label": "Sales", "value": "sales" },
{ "label": "Support", "value": "support" }
]
}
}
PropertyTypeDescription
optionsarray[{ label, value }, ...]
{
"type": "select",
"props": {
"fieldId": "category",
"label": "Category",
"optionsSource": "categories",
"valueField": "id",
"labelField": "name"
}
}
PropertyTypeDefaultDescription
optionsSourcestring-Data source ID
valueFieldstringvalueField for option value
labelFieldstringlabelField for option label
{
"type": "checkbox",
"props": {
"fieldId": "agreeToTerms",
"label": "I agree to the terms and conditions",
"description": "You must agree to continue",
"defaultChecked": false,
"required": true
}
}
PropertyTypeDefaultDescription
fieldIdstringrequiredUnique field identifier
labelstringrequiredCheckbox label
descriptionstring-Help text below label
defaultCheckedbooleanfalseInitial checked state
requiredbooleanfalseMust be checked
disabledboolean/stringfalseDisable checkbox

{
"type": "button",
"props": {
"label": "Save Changes",
"actionType": "workflow",
"workflowId": "save_customer",
"actionParams": {
"id": "{{ variables.customerId }}",
"name": "{{ field.customerName }}",
"email": "{{ field.customerEmail }}"
},
"onComplete": [
{
"type": "navigate",
"navigateTo": "/customers"
}
],
"variant": "default",
"size": "default",
"disabled": "{{ !field.customerName }}"
}
}
PropertyTypeDefaultDescription
labelstringrequiredButton text (supports expressions)
actionTypestringrequirednavigate, workflow, submit, custom
navigateTostring-Target path (for navigate)
workflowIdstring-Workflow to execute
actionParamsobject-Parameters for workflow
onCompletearray-Actions after workflow completes
variantstringdefaultdefault, destructive, outline, secondary, ghost, link
sizestringdefaultdefault, sm, lg
disabledboolean/stringfalseDisable button (supports expressions)

The submit action collects all field values and sends them to a workflow:

{
"type": "button",
"props": {
"label": "Submit Form",
"actionType": "submit",
"workflowId": "process_form",
"actionParams": {
"extraData": "{{ variables.context }}"
}
}
}

This sends { customerName: "...", customerEmail: "...", extraData: "..." } to the workflow.

{
"type": "modal",
"props": {
"title": "Create Customer",
"description": "Add a new customer to the system",
"triggerLabel": "New Customer",
"triggerVariant": "default",
"size": "lg",
"content": {
"type": "column",
"gap": 16,
"children": [
{
"type": "text-input",
"props": { "fieldId": "name", "label": "Name", "required": true }
},
{
"type": "text-input",
"props": { "fieldId": "email", "label": "Email", "inputType": "email" }
}
]
},
"footerActions": [
{
"label": "Create",
"actionType": "submit",
"workflowId": "create_customer",
"closeOnClick": true
}
],
"showCloseButton": true
}
}
PropertyTypeDefaultDescription
titlestringrequiredModal title
descriptionstring-Modal description
triggerLabelstringrequiredButton text to open modal
triggerVariantstringdefaultTrigger button variant
triggerSizestringdefaultTrigger button size
sizestringdefaultsm, default, lg, xl, full
contentobjectrequiredLayout container for modal body
footerActionsarray-Action buttons in footer
showCloseButtonbooleantrueShow X close button

Embed an existing form from the Forms system.

{
"type": "form-embed",
"props": {
"formId": "contact-form-uuid",
"showTitle": true,
"showDescription": true,
"onSubmit": [
{
"type": "set-variable",
"variableName": "lastSubmission",
"variableValue": "{{ workflow.result }}"
},
{
"type": "refresh-table",
"dataSourceKey": "submissions"
}
]
}
}
PropertyTypeDefaultDescription
formIdstringrequiredForm UUID to embed
showTitlebooleanfalseShow form title
showDescriptionbooleanfalseShow form description
showProgressbooleanfalseShow execution progress
onSubmitarray-Actions after form submits

Visual grouping for form inputs.

{
"type": "form-group",
"props": {
"label": "Contact Information",
"description": "Enter your contact details",
"required": true,
"direction": "column",
"gap": 12,
"children": [
{
"type": "text-input",
"props": { "fieldId": "phone", "label": "Phone" }
},
{
"type": "text-input",
"props": { "fieldId": "address", "label": "Address" }
}
]
}
}
PropertyTypeDefaultDescription
labelstring-Group label
descriptionstring-Help text
requiredbooleanfalseMark group as required
directionstringcolumnrow, column
gapnumber8Space between children
childrenarray[]Nested components

Components that accept an icon property use Lucide icons. Common icons:

IconName
Homehome
Settingssettings
Useruser
Usersusers
Plusplus
Pencilpencil
Trashtrash
Downloaddownload
Uploadupload
Searchsearch
Checkcheck
Xx
ChevronRightchevron-right
ArrowRightarrow-right
Mailmail
Phonephone
Calendarcalendar
Clockclock
DollarSigndollar-sign
BarChartbar-chart
FileTextfile-text
Folderfolder