|
| 1 | +# Widget Generation Guide |
| 2 | + |
| 3 | +## 📋 Overview |
| 4 | +Widgets are reusable pieces of UI similar to templates, with placeholders for actual data values. The purpose of this file is to assist developers in creating mosaic renditions for CLTs. |
| 5 | + |
| 6 | +## 🎯 Purpose |
| 7 | +Widgets render data in a structured and unified way across various Salesforce experiences like Slack, Mobile, LEX etc. |
| 8 | + |
| 9 | +## Schema Grounding |
| 10 | +Widget generation is **always schema-grounded** using a CLT's schema. The schema describes the data shape the widget should render. Extract property names, types, required vs optional, and nesting from the schema; then follow the full **Workflow** below, using this extracted structure to guide every step. Do not add or remove properties relative to the schema. |
| 11 | + |
| 12 | +## ⚙️ Composition |
| 13 | +A widget is a UEM (Unified Experience Model) tree of blocks and regions. The widget you return must follow the Typescript interfaces below: |
| 14 | + |
| 15 | +```ts |
| 16 | +interface BlockType { |
| 17 | + type: 'block' |
| 18 | + definition: string // {namespace}/{blockName} |
| 19 | + attributes?: Record<string, any> |
| 20 | + children?: (BlockType | RegionType)[] |
| 21 | +} |
| 22 | + |
| 23 | +interface RegionType { |
| 24 | + type: 'region' |
| 25 | + name: string |
| 26 | + children: BlockType[] |
| 27 | +} |
| 28 | +``` |
| 29 | +--- |
| 30 | + |
| 31 | +## 🔧 Available Metadata Actions |
| 32 | + |
| 33 | +### When to Use Each Action |
| 34 | + |
| 35 | +#### discoverUiComponents |
| 36 | + |
| 37 | +**Purpose:** Discover the palette of available blocks that can be used in widget composition. |
| 38 | + |
| 39 | +**Use for:** Finding available blocks before building your widget structure. |
| 40 | + |
| 41 | +**Input Parameters:** |
| 42 | +- `actionName` (**required***): "discoverUiComponents" |
| 43 | +- `metadataType` (**required**): "FRAGMENT" |
| 44 | +- `parameters` (**required**): JSON object with the below fields |
| 45 | + - `pageType` (**required**): "FRAGMENT" |
| 46 | + - `pageContext` (optional): JSON object - not required for FRAGMENT type |
| 47 | + - `searchQuery` (optional): String to filter components by name or description |
| 48 | + |
| 49 | +**Returns:** List of components with: |
| 50 | +- `definition`: Fully qualified name (e.g., "namespace/definiton") |
| 51 | +- `description`: Component description |
| 52 | +- `label`: Human-readable label |
| 53 | +- `attributes`: Optional attribute metadata |
| 54 | + |
| 55 | +#### getUiComponentSchemas |
| 56 | + |
| 57 | +**Purpose:** Get detailed JSON schemas for component configuration, including property types, required vs optional fields, and validation rules. |
| 58 | + |
| 59 | +**Use for:** You know which components you want but need to understand their properties before adding them to your widget. |
| 60 | + |
| 61 | +**Input Parameters:** |
| 62 | +- `actionName` (**required***): "getUiComponentSchemas" |
| 63 | +- `metadataType` (**required**): "FRAGMENT" |
| 64 | +- `parameters` (**required**): JSON object with the below fields |
| 65 | + - `pageType` (**required**): "FRAGMENT" |
| 66 | + - `componentDefinitions` (**required**): List of fully qualified names (e.g., ["namespace/definition"]) |
| 67 | + - **CRITICAL**: NEVER include "tile/mosaic" in this list. "tile/mosaic" is a container component used in renderer.json structure and **should not** be passed to getUiComponentSchemas |
| 68 | + - `pageContext` (optional): JSON object - not required for FRAGMENT type |
| 69 | + - `includeKnowledge` (optional): Boolean, defaults to true - includes additional component-specific guidance |
| 70 | + |
| 71 | +**Returns:** |
| 72 | +- `componentSchemas`: List of results (supports partial failures) |
| 73 | +- **Success entries**: Contains JSON schema with property definitions, types, constraints |
| 74 | +- **Failure entries**: Contains error message explaining why schema couldn't be retrieved |
| 75 | +- `$defs`: Schema definitions and references (if schema transformation applied) |
| 76 | + |
| 77 | +**Key Feature:** Supports partial failures - if some components can't be found, you still get schemas for the successful ones. |
| 78 | + |
| 79 | +--- |
| 80 | + |
| 81 | +## Attribute binding using placeholder syntax |
| 82 | + |
| 83 | +- **Where to use:** When block properties must display or pass runtime data from the grounding schema, use the **Placeholder Syntax** below so that the runtime binds values into the widget. Check each block's schema (from `getUiComponentSchemas`) for the correct property name (e.g. `value`, `text`, `label`). |
| 84 | +- **Placeholder Syntax:** Use `{!$attrs.<attrName>}` as the placeholder for each block property that should receive data. |
| 85 | + `<attrName>` **must** match the property name from the grounding schema so that the runtime can resolve its value. |
| 86 | + Example: for a schema property `title`, set the block property to `{!$attrs.title}`. |
| 87 | +- **List / iterative data:** Only the children (list items) hold bound values; the parent list block does not. For each item inside a list (e.g. `tile/listItem`), use `{!$attrs.<listAttrName>.item}` so the runtime binds the current item. `<listAttrName>` MUST match the schema property name of the list. Example: for `icons`, use `"{!$attrs.icons.item}"` on the list item. |
| 88 | + |
| 89 | +--- |
| 90 | + |
| 91 | +## 💡Workflow |
| 92 | + |
| 93 | +1. **Schema Parsing** |
| 94 | +- Parse the schema and extract: property names, types, required vs optional, and nested structure. Use this as the **widget spec**. |
| 95 | + |
| 96 | +2. **Discover Available Blocks** (**REQUIRED** - do NOT skip) |
| 97 | +- Use **discoverUiComponents metadata action** above to explore what blocks are available. |
| 98 | +- Use property types from the **widget spec** to inform `searchQuery` (e.g. text → "text", number → "number"). |
| 99 | + |
| 100 | +3. **Select Components** |
| 101 | +- Choose blocks that can represent each property in the **widget spec** from the results of step 2. |
| 102 | + |
| 103 | +4. **Get Component Schemas** (**REQUIRED** - do NOT skip) |
| 104 | +- Use **getUiComponentSchemas metadata action** with the selected block definitions from step 3 and review block properties' metadata. |
| 105 | + |
| 106 | +5. **Build Widget** |
| 107 | +- Construct the UEM tree. Map each property in the **widget spec** to block properties and preserve order of the **widget spec**. |
| 108 | +- For block properties that must show or pass runtime data, use the placeholder syntax (see **Attribute binding using placeholder syntax** above). |
| 109 | +- Use block properties from the schemas retrieved in step 4. |
| 110 | + |
| 111 | +6. **Write output to CLT Bundle** |
| 112 | +- Always write to `lightningTypes/<TypeName>/lightningDesktopGenAi/renderer.json` (or the correct target subfolder for the product surface, e.g. `experienceBuilder/`, `lightningMobileGenAi/`, `enhancedWebChat/` when applicable). |
| 113 | + Check **required root override pattern** below - |
| 114 | + `renderer.componentOverrides["$"] = { "type": "mosaic", "definition": "tile/mosaic", "children": [ ... ] — array of UEM nodes - contains the widget UEM generated using the **Workflow** steps 1-5 above }` |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## ⚠️ Important Notes |
| 119 | + |
| 120 | +- **widget spec** includes both required and optional attributes - review carefully to ensure valid configuration. |
| 121 | +- When using **`execute_metadata_action`** tool, always supply **`parameters`** with the required fields above; missing `parameters` or required keys causes hard failures, not partial results. |
| 122 | +- Block definitions always follow the `{namespace}/{blockName}` convention. |
| 123 | +- Use the same definition format returned by `discoverUiComponents` when calling `getUiComponentSchemas` |
| 124 | +- Placeholder syntax for non-list properties is `{!$attrs.<attrName>}` and for list properties is `{!$attrs.<listAttrName>.item}`. |
0 commit comments