Page Structure
This reference documents the top-level types that make up an Aptean Mesh page definition. Every property name matches the Kotlin source in LatticeClient exactly.
Page
The root object. Defined in Page.kt as a @Serializable data class.
| Property | Type | Default | Description |
|---|---|---|---|
pageId | string | "" | Unique identifier for this page within the App Bundle. Used for navigation and caching. |
service | string? | null | The Mobile Service Code that maps to an AL codeunit via the Service Registry. Required if the page makes API calls. |
workflow | string? | null | Optional workflow identifier used to scope RPC calls to a specific BC workflow instance. |
header | Header? | null | Page header configuration (title bar, drawer menu). |
body | Component[] | [] | Array of UI components that make up the main scrollable content area. |
footer | Footer? | null | Footer configuration with action buttons. |
contract | Contract? | null | Data contract defining actions, filters, and page behaviors. |
Minimal Page Example
{
"pageId": "HELLO-WORLD",
"header": {
"title": "Hello World"
},
"body": [
{ "type": "text", "text": "Welcome to Aptean Mesh!" }
]
}
Complete Page Example
This example shows how header, body, footer, and contract connect:
{
"pageId": "HOME",
"service": "HOMESERVICE",
"header": {
"title": "Lattice",
"refresh": true,
"showFilterInHeader": true,
"drawer": [
{
"title": "Bin Contents",
"icon": "inventory",
"actionId": "navigateToBinContents",
"section": "header"
}
]
},
"body": [
{
"type": "input",
"inputId": "query",
"placeholder": "Search documents...",
"action": "onLoadDocuments"
},
{
"type": "selector",
"selectorType": "SEGMENT",
"valueKey": "selectedType",
"options": ["Inbound", "Internal", "Outbound"],
"onSelectAction": "onLoadDocuments"
},
{
"type": "repeater",
"dataKey": "documents",
"key": "Document No",
"template": "CARD",
"onTapAction": "onDocumentTap",
"emptyMessage": "No documents found",
"fields": [
{ "key": "Type", "label": "Type" },
{ "key": "Document No", "label": "Document No" }
]
}
],
"footer": {
"actions": [
{ "label": "Refresh", "action": "onLoadDocuments", "icon": "refresh", "tone": "HIGH" }
]
},
"contract": {
"initialAction": "onLoadDocuments",
"actions": [
{
"id": "onLoadDocuments",
"type": "api",
"method": "GetDocuments",
"params": ["query", "selectedType"]
},
{
"id": "onDocumentTap",
"type": "api",
"method": "SelectDocument",
"params": ["Document No", "Type"]
},
{
"id": "navigateToBinContents",
"type": "navigate",
"destination": "BINCONTENTS"
}
]
}
}
Header
The page header displayed in the app bar. Defined in Header.kt.
| Property | Type | Default | Description |
|---|---|---|---|
title | string | required | Static title text displayed in the app bar. |
titleKey | string? | null | Data binding key to dynamically resolve the title from page data. Overrides title when data is available. |
subtitle | string? | null | Static subtitle text displayed below the title. |
subtitleKey | string? | null | Data binding key to dynamically resolve the subtitle from page data. |
refresh | boolean | false | When true, enables pull-to-refresh gesture that re-executes the contract's initialAction. |
drawer | DrawerItem[] | [] | Navigation items shown in the hamburger drawer menu. |
showFilterInHeader | boolean | true | Whether to show the filter button in the header bar. |
Example
{
"header": {
"title": "Detail Screen",
"titleKey": "documentTitle",
"subtitleKey": "lineCount",
"refresh": true
}
}
When the API response contains { "documentTitle": "Pick #WH-001", "lineCount": "3 lines" }, the header displays "Pick #WH-001" as the title and "3 lines" as the subtitle.
DrawerItem
A navigation entry in the drawer menu. Defined in Header.kt.
| Property | Type | Default | Description |
|---|---|---|---|
title | string | required | Label text for this menu item. |
icon | string? | null | Material icon name displayed alongside the title (e.g., "inventory", "tune"). |
actionId | string | required | Action identifier to execute when this item is selected. Must reference an action in contract.actions. |
value | string? | null | Static display value shown next to the title. |
valueKey | string? | null | Data binding key to dynamically resolve the display value. |
changeActionId | string? | null | Action identifier for a "Change" button, used for switchable items (e.g., changing the active warehouse). |
section | string? | null | Which section of the drawer this item belongs to: "header", "body", or "footer". |
Example
{
"drawer": [
{
"title": "Ad-Hoc Movement",
"icon": "move_item",
"actionId": "onAdHocMovement",
"section": "header"
},
{
"title": "Warehouse",
"icon": "warehouse",
"actionId": "showWarehouse",
"valueKey": "currentWarehouse",
"changeActionId": "changeWarehouse",
"section": "body"
}
]
}
Footer
The page footer containing action buttons. Defined in Footer.kt. The client displays up to 3 action buttons directly -- any additional actions overflow into an expandable menu.
| Property | Type | Default | Description |
|---|---|---|---|
actions | ActionItem[] | [] | List of action buttons. First 3 are always visible; the rest appear in an overflow menu. |
enableSidePane | boolean | false | When true, shows a toggle button to open/close the side pane for dual-pane navigation. |
Example
{
"footer": {
"actions": [
{ "label": "Release", "action": "releaseOrder", "icon": "check", "tone": "HIGH" },
{ "label": "Print", "action": "printOrder", "icon": "print", "tone": "MEDIUM" }
],
"enableSidePane": true
}
}
ActionItem
An action button used in footers and card context menus. Defined in Footer.kt.
| Property | Type | Default | Description |
|---|---|---|---|
label | string | required | Text displayed on the button. |
action | string | required | Action identifier to execute. Must reference an action in contract.actions. |
icon | string? | null | Material icon name displayed alongside the label. |
tone | Tone | MEDIUM | Visual emphasis level affecting button color. See Tone enum. |
enabled | boolean | true | Whether the button is interactive. Disabled buttons are visually dimmed. |
enabledKey | string? | null | Data binding key that dynamically controls whether the button is enabled. |
Contract
The data contract controlling how the page interacts with backend services. Defined in Contract.kt.
| Property | Type | Default | Description |
|---|---|---|---|
initialAction | string? | null | Action identifier to execute automatically when the page loads. |
scanAction | string? | null | Action identifier to execute when a barcode/QR scan is triggered. Falls back to initialAction if not specified. |
actions | IAction[] | [] | All action definitions available on this page. See Data Contract and Actions. |
filters | FilterDefinition[] | [] | Filter definitions for the filter panel. |
The contract resolves action references at parse time:
resolvedInitialAction-- Finds theApiActionmatchinginitialActionby ID.resolvedScanAction-- Finds theApiActionmatchingscanActionby ID. Falls back toresolvedInitialActionifscanActionis not set.
Example
{
"contract": {
"initialAction": "onLoad",
"scanAction": "onScan",
"actions": [
{
"id": "onLoad",
"type": "api",
"method": "Initialize",
"params": ["locationFilter", "workflow"]
},
{
"id": "onScan",
"type": "api",
"method": "HandleScan",
"params": ["value", "workflow"]
},
{
"id": "goToDetails",
"type": "navigate",
"destination": "DETAILS"
}
],
"filters": [
{
"id": "assignment",
"label": "Assignment",
"mode": "DROPDOWN",
"options": ["Assigned to Me", "Unassigned", "All"],
"defaultValue": "All"
}
]
}
}
EventContext
A runtime object (not serialized in JSON) that the client constructs when dispatching events. Defined in EventContext.kt. Included here for completeness -- developers do not author this in page JSON, but it appears in client logs and debugging.
| Property | Type | Description |
|---|---|---|
eventKey | string | The key identifying the event (e.g., an action ID or "hardware_scan"). |
service | string? | The service code from the page definition. |
workflow | string? | The workflow identifier from the page definition. |
contract | Contract? | The page's contract, used to resolve action definitions. |
dataContext | Map<string, any?> | Current page data snapshot, including input values and API response data. |
Tone Enum
The Tone enum is used across multiple types (ActionItem, CardField, ButtonComponent, TextComponent, TrailingAction). Defined in ToneColors.kt.
| Value | Description |
|---|---|
LOW | Subtle, de-emphasized appearance |
MEDIUM | Default neutral appearance |
HIGH | Primary/accent color, strong emphasis |
ERROR | Red, used for destructive or error states |
SUCCESS | Green, used for positive/completed states |
WARNING | Amber/yellow, used for caution states |
INFO | Blue/informational appearance |
How the Parts Connect
Page
+-- header (Header)
| +-- title / titleKey
| +-- subtitle / subtitleKey
| +-- drawer[] (DrawerItem)
| +-- actionId --> contract.actions[].id
|
+-- body[] (Component)
| +-- Each component binds to data via *Key properties
| +-- Action properties (action, onTapAction, etc.) --> contract.actions[].id
|
+-- footer (Footer)
| +-- actions[] (ActionItem)
| +-- action --> contract.actions[].id
|
+-- contract (Contract)
+-- initialAction --> actions[].id (auto-executed on page load)
+-- scanAction --> actions[].id (executed on barcode scan)
+-- actions[] (IAction) (all action definitions)
+-- filters[] (FilterDefinition) (filter panel config)
All action references (actionId, action, onTapAction, onSelectAction, loadAction, selectAction) point to an entry in contract.actions by its id field.