App Builder Schema
Complete JSON schema reference for application definitions
Application Definition
Section titled “Application Definition”The root structure for an App Builder application:
{ "id": "my-app", "name": "My Application", "description": "Application description", "version": "1.0.0", "pages": [], "navigation": {}, "permissions": {}, "globalDataSources": [], "globalVariables": {}}| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique application identifier |
name | string | Yes | Display name |
description | string | No | Application description |
version | string | Yes | Semantic version |
pages | PageDefinition[] | Yes | Application pages |
navigation | NavigationConfig | No | Sidebar and header configuration |
permissions | PermissionConfig | No | App-level access control |
globalDataSources | DataSource[] | No | Data sources available to all pages |
globalVariables | object | No | Initial variables for all pages |
PageDefinition
Section titled “PageDefinition”{ "id": "dashboard", "title": "Dashboard", "path": "/", "layout": {}, "dataSources": [], "variables": {}, "launchWorkflowId": "load_dashboard_data", "launchWorkflowParams": {}, "permission": {}}| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique page identifier |
title | string | Yes | Page title (shown in browser tab) |
path | string | Yes | URL path (e.g., /, /users/:id) |
layout | LayoutContainer | Yes | Root layout for page content |
dataSources | DataSource[] | No | Page-specific data sources |
variables | object | No | Initial page variables |
launchWorkflowId | string | No | Workflow to run on page mount |
launchWorkflowParams | object | No | Parameters for launch workflow |
permission | PagePermission | No | Page access control |
Path Parameters
Section titled “Path Parameters”Use :param syntax for dynamic routes:
{ "path": "/users/:userId" }{ "path": "/org/:orgId/projects/:projectId" }Access in expressions: {{ params.userId }}
LayoutContainer
Section titled “LayoutContainer”{ "type": "column", "gap": 16, "padding": 24, "align": "stretch", "justify": "start", "columns": 3, "children": []}| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | row, column, or grid |
gap | number | No | Space between children (pixels) |
padding | number | No | Internal padding (pixels) |
align | string | No | Cross-axis alignment |
justify | string | No | Main-axis alignment |
columns | number | No | Grid columns (grid type only) |
children | array | No | Nested layouts or components |
Align values: start, center, end, stretch
Justify values: start, center, end, between, around
AppComponent
Section titled “AppComponent”Base structure for all components:
{ "id": "component-1", "type": "heading", "visible": "{{ user.isActive }}", "width": "1/2", "props": {}}| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique component identifier |
type | string | Yes | Component type (see Components Reference) |
visible | string | No | Visibility expression |
width | string | No | Component width |
props | object | Yes | Component-specific properties |
Width values: auto, full, 1/2, 1/3, 1/4, 2/3, 3/4
DataSource
Section titled “DataSource”{ "id": "customers", "type": "workflow", "workflowId": "get_customers", "inputParams": { "status": "active" }, "autoRefresh": false, "refreshInterval": 30000}| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Data source identifier |
type | string | Yes | workflow, data-provider, api, static, computed |
workflowId | string | Conditional | Workflow ID (for workflow type) |
dataProviderId | string | Conditional | Data provider ID (for data-provider type) |
endpoint | string | Conditional | API URL (for api type) |
data | any | Conditional | Static data (for static type) |
expression | string | Conditional | Expression (for computed type) |
inputParams | object | No | Parameters (supports expressions) |
autoRefresh | boolean | No | Auto-refresh enabled |
refreshInterval | number | No | Refresh interval in milliseconds |
Data Source Types
Section titled “Data Source Types”workflow: Execute a workflow and use its return value:
{ "id": "orders", "type": "workflow", "workflowId": "get_orders", "inputParams": { "userId": "{{ user.id }}" }}data-provider: Use a registered data provider:
{ "id": "departments", "type": "data-provider", "dataProviderId": "get_departments"}static: Inline data:
{ "id": "statusOptions", "type": "static", "data": [ { "label": "Active", "value": "active" }, { "label": "Inactive", "value": "inactive" } ]}NavigationConfig
Section titled “NavigationConfig”{ "showHeader": true, "showSidebar": true, "logoUrl": "https://example.com/logo.png", "brandColor": "#4F46E5", "sidebar": []}| Field | Type | Description |
|---|---|---|
showHeader | boolean | Show application header |
showSidebar | boolean | Show navigation sidebar |
logoUrl | string | Logo image URL |
brandColor | string | Primary brand color (hex) |
sidebar | NavItem[] | Sidebar navigation items |
NavItem
Section titled “NavItem”{ "id": "nav-dashboard", "label": "Dashboard", "icon": "home", "path": "/", "visible": "{{ user.role != 'guest' }}", "order": 1, "isSection": false, "children": []}| Field | Type | Description |
|---|---|---|
id | string | Unique nav item ID |
label | string | Display text |
icon | string | Lucide icon name |
path | string | Navigation path |
visible | string | Visibility expression |
order | number | Sort order |
isSection | boolean | Render as section header |
children | NavItem[] | Nested nav items |
Section Example:
{ "id": "admin-section", "label": "Administration", "isSection": true, "visible": "{{ user.role == 'admin' }}", "children": [ { "id": "users", "label": "Users", "icon": "users", "path": "/admin/users" }, { "id": "settings", "label": "Settings", "icon": "settings", "path": "/admin/settings" } ]}PermissionConfig
Section titled “PermissionConfig”Application-level permissions:
{ "public": false, "defaultLevel": "none", "rules": [ { "role": "admin", "level": "admin" }, { "role": "manager", "level": "edit" }, { "role": "*", "level": "view" } ]}| Field | Type | Description |
|---|---|---|
public | boolean | Allow unauthenticated access |
defaultLevel | string | Default permission level |
rules | PermissionRule[] | Role-based permission rules |
PermissionRule
Section titled “PermissionRule”{ "role": "admin", "level": "admin" }| Field | Type | Description |
|---|---|---|
role | string | Role name or * for all authenticated users |
level | string | none, view, edit, admin |
PagePermission
Section titled “PagePermission”Page-level access control:
{ "allowedRoles": ["admin", "manager"], "accessExpression": "{{ user.department == 'engineering' }}", "redirectTo": "/access-denied"}| Field | Type | Description |
|---|---|---|
allowedRoles | string[] | Roles that can access (* for all authenticated) |
accessExpression | string | Expression that must evaluate to true |
redirectTo | string | Redirect path if access denied |
OnCompleteAction
Section titled “OnCompleteAction”{ "type": "navigate", "navigateTo": "/customers/{{ workflow.result.id }}"}{ "type": "set-variable", "variableName": "lastCreated", "variableValue": "{{ workflow.result }}"}{ "type": "refresh-table", "dataSourceKey": "customers"}| Field | Type | Applies To | Description |
|---|---|---|---|
type | string | All | navigate, set-variable, refresh-table |
navigateTo | string | navigate | Target path |
variableName | string | set-variable | Variable to set |
variableValue | any | set-variable | Value to assign |
dataSourceKey | string | refresh-table | Data source ID |
TableColumn
Section titled “TableColumn”{ "key": "user.email", "header": "Email", "type": "text", "width": 200, "sortable": true, "badgeColors": {}}| Field | Type | Description |
|---|---|---|
key | string | Data field path (dot notation supported) |
header | string | Column header text |
type | string | text, number, date, badge |
width | number/string | Column width |
sortable | boolean | Enable column sorting |
badgeColors | object | Value-to-color mapping (for badge type) |
TableAction
Section titled “TableAction”{ "label": "Delete", "icon": "trash", "variant": "destructive", "visible": "{{ row.canDelete }}", "disabled": "{{ row.isLocked }}", "onClick": { "type": "workflow", "workflowId": "delete_item", "actionParams": { "id": "{{ row.id }}" } }, "confirm": { "title": "Confirm Delete", "message": "Delete {{ row.name }}?", "confirmLabel": "Delete", "cancelLabel": "Cancel" }}| Field | Type | Description |
|---|---|---|
label | string | Action button label |
icon | string | Lucide icon name |
variant | string | default, destructive, outline, ghost |
visible | string | Visibility expression |
disabled | string | Disabled expression |
onClick | object | Action configuration |
confirm | ConfirmConfig | Confirmation dialog |
ConfirmConfig
Section titled “ConfirmConfig”{ "title": "Confirm Action", "message": "Are you sure?", "confirmLabel": "Confirm", "cancelLabel": "Cancel"}| Field | Type | Default | Description |
|---|---|---|---|
title | string | required | Dialog title |
message | string | required | Confirmation message |
confirmLabel | string | Confirm | Confirm button text |
cancelLabel | string | Cancel | Cancel button text |
SelectOption
Section titled “SelectOption”{ "label": "Active", "value": "active" }| Field | Type | Description |
|---|---|---|
label | string | Display text |
value | string | Option value |
Complete Example
Section titled “Complete Example”{ "id": "customer-portal", "name": "Customer Portal", "version": "1.0.0", "permissions": { "public": false, "rules": [ { "role": "*", "level": "view" } ] }, "navigation": { "showSidebar": true, "sidebar": [ { "id": "home", "label": "Dashboard", "icon": "home", "path": "/" }, { "id": "customers", "label": "Customers", "icon": "users", "path": "/customers" } ] }, "pages": [ { "id": "dashboard", "title": "Dashboard", "path": "/", "dataSources": [ { "id": "stats", "type": "workflow", "workflowId": "get_dashboard_stats" } ], "layout": { "type": "column", "gap": 24, "padding": 24, "children": [ { "id": "welcome", "type": "heading", "props": { "text": "Welcome, {{ user.name }}", "level": 1 } }, { "type": "grid", "columns": 3, "gap": 16, "children": [ { "id": "stat-customers", "type": "stat-card", "props": { "title": "Total Customers", "value": "{{ data.stats.customerCount }}", "icon": "users" } }, { "id": "stat-revenue", "type": "stat-card", "props": { "title": "Revenue", "value": "${{ data.stats.revenue }}", "icon": "dollar-sign" } }, { "id": "stat-orders", "type": "stat-card", "props": { "title": "Active Orders", "value": "{{ data.stats.activeOrders }}", "icon": "shopping-cart" } } ] } ] } }, { "id": "customers", "title": "Customers", "path": "/customers", "dataSources": [ { "id": "customers", "type": "workflow", "workflowId": "list_customers" } ], "layout": { "type": "column", "gap": 16, "padding": 24, "children": [ { "type": "row", "justify": "between", "align": "center", "children": [ { "id": "title", "type": "heading", "props": { "text": "Customers", "level": 1 } }, { "id": "add-btn", "type": "button", "props": { "label": "Add Customer", "actionType": "navigate", "navigateTo": "/customers/new" } } ] }, { "id": "table", "type": "data-table", "props": { "dataSource": "customers", "searchable": true, "paginated": true, "columns": [ { "key": "name", "header": "Name", "sortable": true }, { "key": "email", "header": "Email" }, { "key": "status", "header": "Status", "type": "badge" } ], "onRowClick": { "type": "navigate", "navigateTo": "/customers/{{ row.id }}" }, "rowActions": [ { "label": "Edit", "icon": "pencil", "onClick": { "type": "navigate", "navigateTo": "/customers/{{ row.id }}/edit" } } ] } } ] } } ]}Type Summary
Section titled “Type Summary”| Type | Values |
|---|---|
| ComponentType | heading, text, html, card, divider, spacer, button, stat-card, image, badge, progress, data-table, tabs, file-viewer, modal, text-input, number-input, select, checkbox, form-embed, form-group |
| LayoutType | row, column, grid |
| ActionType | navigate, workflow, submit, set-variable, refresh-table, custom |
| PermissionLevel | none, view, edit, admin |
| ButtonVariant | default, destructive, outline, secondary, ghost, link |
| ButtonSize | default, sm, lg |
| ColumnType | text, number, date, badge |
| Width | auto, full, 1/2, 1/3, 1/4, 2/3, 3/4 |
| Align | start, center, end, stretch |
| Justify | start, center, end, between, around |