13 KiB
| name | description |
|---|---|
| salesforce-flexipage | Generate FlexiPage metadata using CLI bootstrapping and MCP actions for component discovery. Use when creating Record Pages, App Pages, or Home Pages in Lightning Experience. |
When to Use This Skill
Use this skill when you need to:
- Create Lightning pages (Record, App, or Home pages)
- Build custom page layouts in Lightning Experience
- Add components to Lightning pages
- Configure page structure and components
- Troubleshoot deployment errors related to FlexiPages
Specification
FlexiPage Generation Guide
Overview
Generate Lightning pages (RecordPage, AppPage, HomePage) using CLI bootstrapping + MCP actions for component discovery and configuration.
Quick Start Workflow
Step 1: Bootstrap with CLI
sf template generate flexipage \
--name <PageName> \
--template <RecordPage|AppPage|HomePage> \
--sobject <SObject> \
--primary-field <Field1> \
--secondary-fields <Field2,Field3> \
--detail-fields <Field4,Field5,Field6,Field7> \
--output-dir force-app/main/default/flexipages
Template-specific requirements:
- RecordPage: Requires
--sobject(e.g., Account, Custom_Object__c) - RecordPage: Requires
--primary-fieldand--secondary-fieldsfor dynamic highlights,--detail-fieldsfor full record details. Use the most important identifying field as primary, e.g. Name. Use the secondary fields (max 12, recommended 4-6) to show a summary of the record. Use Use detail fields to show the full details of the record. - AppPage: No additional requirements
- HomePage: No additional requirements
What you get:
- Valid FlexiPage XML with correct structure
- Pre-configured regions and basic components
- Proper field references and facet structure
- Ready to deploy as-is or enhance further
Step 2: Deploy Base Page
sf project deploy start --source-dir force-app/main/default/flexipages
Deploy early, deploy often. Start with the bootstrapped page, validate it works, then enhance.
Step 3: Enhance with MCP Actions (Optional)
If you need to add more components or customize:
A. Discover Available Components
DISCOVER_UI_COMPONENTS
Returns: List of components available for this page type with descriptions.
B. Get Component Schemas
GET_UI_COMPONENT_SCHEMAS
Returns: JSON schemas showing required/optional properties, types, data sources. Also includes instructions specific to each component.
C. Get Data Source Values
GET_DATA_SOURCE_VALUES
Returns: Valid values for properties with data sources.
Step 4: Update and Redeploy
Modify the generated XML, adding components discovered via MCP. Deploy incrementally.
Critical XML Rules
1. Property Value Encoding (MOST COMMON ERROR)
Any property value with HTML/XML characters MUST be manually encoded in the following order (wrong order causes double-encoding corruption):
1. & → & (FIRST! Encode this before others)
2. < → <
3. > → >
4. " → "
5. ' → '
Wrong:
<value><b>Important</b> text</value>
Correct:
<value><b>Important</b> text</value>
Check your XML: Search for <value> tags - they should never contain raw < or > characters.
2. Field References
ALWAYS: Record.{FieldApiName}
NEVER: {ObjectName}.{FieldApiName}
<!-- Correct -->
<fieldItem>Record.Name</fieldItem>
<!-- Wrong -->
<fieldItem>Account.Name</fieldItem>
3. Region vs Facet Types
Template Regions (header, main, sidebar):
<name>header</name>
<type>Region</type>
Component Facets (internal slots like fieldSection columns):
<name>Facet-12345</name>
<type>Facet</type>
Rule: If it's a template region name → Region. If it's a component slot → Facet.
4. fieldInstance Structure
Every fieldInstance requires:
<itemInstances>
<fieldInstance>
<fieldInstanceProperties>
<name>uiBehavior</name>
<value>none</value> <!-- none|readonly|required -->
</fieldInstanceProperties>
<fieldItem>Record.FieldName__c</fieldItem>
<identifier>RecordFieldName_cField</identifier>
</fieldInstance>
</itemInstances>
Rules:
- Each fieldInstance in its own
<itemInstances>wrapper - Must have
fieldInstancePropertieswithuiBehavior - Use
Record.{Field}format
Using MCP Actions
When to Use Each Action
DISCOVER_UI_COMPONENTS
When: You want to see what components are available for your page type.
Returns: Component list with names, namespaces, descriptions.
Use for: Finding components to add to your bootstrapped page.
GET_UI_COMPONENT_SCHEMAS
When: You know which components you want but need to understand their properties. If you have issues configuring a component and need more detailed instructions or knowledge.
Returns: JSON schemas with:
- Required vs optional properties
- Property types (string, boolean, array, etc.)
- Data source references
- Descriptions
- Additional component-specific instructions or knowledge, often useful for more complex components.
Use for: Understanding how to configure components before adding to XML.
GET_DATA_SOURCE_VALUES
When: A component property references a data source and you need valid values.
Returns: Valid values (e.g., "1", "2", "3" for column count).
Use for: Ensuring property values match allowed options.
Common Deployment Errors
"Invalid field reference"
Cause: Used ObjectName.Field instead of Record.Field
Fix: Change to Record.{FieldApiName}
"Element fieldInstance is duplicated"
Cause: Multiple fieldInstances in one itemInstances
Fix: Each fieldInstance needs its own <itemInstances> wrapper
"Missing fieldInstanceProperties"
Cause: No uiBehavior specified
Fix: Add fieldInstanceProperties with uiBehavior
"Invalid component property"
Cause: Wrong property name or format
Fix: Use GET_UI_COMPONENT_SCHEMAS to see exact property names and types, or to find additional documentation.
"Unused Facet"
Cause: Facet defined but not referenced by any component
Fix: Remove Facet or reference it in a component property
"XML parsing error"
Cause: Unencoded HTML/XML in property values
Fix: Manually encode <, >, &, ", ' in all <value> tags
"Cannot create component with namespace"
Cause: Invalid page name (don't use __c suffix in page names)
Fix: Use "Volunteer_Record_Page" not "Volunteer__c_Record_Page"
"Region specifies mode that parent doesn't support"
Cause: Added <mode> tag to region
Fix: Remove <mode> tags - they're not needed for standard regions
Component-Specific Tips
dynamicHighlights (RecordPage Header)
Location: Must be in header region.
Explicit Fields (via CLI): Use the most important fields to show a summary of the record. The single primary field is used to identify the record, like a name. The secondary fields (max 12, recommended 6) are used as a summary of the record.
--primary-field Name
--secondary-fields Phone,Industry,AnnualRevenue
CLI generates Facets with field references automatically.
fieldSection
Use for: Displaying fields in columns.
Structure: Three-level nesting:
- Template Region (Region type)
- Column Facets (Facet type)
- Field Facets (Facet type)
Referenced in component property:
<componentInstanceProperties>
<name>columns</name>
<value>Facet-{uuid}</value>
</componentInstanceProperties>
Incremental Development Pattern
Philosophy: Deploy small, working increments. Don't build entire complex page at once.
Process:
- CLI bootstrap → Deploy base page
- Add one component → Deploy
- Add another component → Deploy
- Repeat until complete
Benefits:
- Isolated errors (know exactly what broke)
- Faster debugging
- Build confidence with each success
- Get user feedback early
Anti-pattern: Building entire complex page → one giant error cascade.
Adding Components to Existing FlexiPages
Workflow
When user provides an existing FlexiPage file path:
- Read the file using native file I/O
- Parse XML to extract:
- Existing component identifiers
- Available regions (parse from file, don't assume names)
- Existing facets
- Use MCP actions for discovery:
- DISCOVER_UI_COMPONENTS (find available components)
- GET_UI_COMPONENT_SCHEMAS (understand properties and get additional documentation)
- GET_DATA_SOURCE_VALUES (validate data source values)
- Generate component XML (apply all rules from "Critical XML Rules" section)
- Insert into appropriate region
- Write modified XML back to file
- Deploy:
sf project deploy start --source-dir force-app/...
Generating Unique Identifiers
Algorithm:
1. Extract all existing <identifier> values from XML
2. Generate base name: {componentType}_{context}
Examples: "relatedList_contacts", "richText_header", "tabs_main"
3. Find first available number:
- Try "{base}_1"
- If exists, try "{base}_2", "{base}_3", etc.
- Use first available
Examples:
- First contacts related list:
relatedList_contacts_1 - Second contacts related list:
relatedList_contacts_2 - Rich text in header:
richText_header_1 - Field section:
fieldSection_details_1
Facet Naming - Two Patterns:
-
Named facets (for major content areas):
detailTabContent(detail tab content)maintabs(main tab container)sidebartabs(sidebar tab container)- Use when facet represents meaningful content area
-
UUID facets (for internal structure):
- Format:
Facet-{8hex}-{4hex}-{4hex}-{4hex}-{12hex} - Example:
Facet-66d5a4b3-bf14-4665-ba75-1ceaa71b2cde - Use for field section columns, nested containers, anonymous slots
- Format:
Region Selection
Parse regions from file - don't hardcode names. Templates vary:
flexipage:recordHomeTemplateDesktop→header,main,sidebarruntime_service_fieldservice:...→header,main,footer- Others may have different region names
Default placement: End of target region (after last <itemInstances>)
Insertion pattern:
<flexiPageRegions>
<name>main</name> <!-- or whatever region name exists -->
<type>Region</type>
<itemInstances><!-- Existing component 1 --></itemInstances>
<itemInstances><!-- Existing component 2 --></itemInstances>
<itemInstances>
<!-- INSERT NEW COMPONENT HERE -->
</itemInstances>
</flexiPageRegions>
Container Components with Facets
Components like tabs, accordions, field sections require facets.
Pattern:
<!-- 1. Component in region -->
<flexiPageRegions>
<itemInstances>
<componentInstance>
<componentName>flexipage:tabset2</componentName>
<identifier>tabs_main_1</identifier>
<componentInstanceProperties>
<name>tabs</name>
<value>tab1_content</value>
<value>tab2_content</value>
</componentInstanceProperties>
</componentInstance>
</itemInstances>
<name>main</name>
<type>Region</type>
</flexiPageRegions>
<!-- 2. Facets (siblings of region, NOT nested inside) -->
<flexiPageRegions>
<itemInstances><!-- Tab 1 content --></itemInstances>
<name>tab1_content</name>
<type>Facet</type>
</flexiPageRegions>
<flexiPageRegions>
<itemInstances><!-- Tab 2 content --></itemInstances>
<name>tab2_content</name>
<type>Facet</type>
</flexiPageRegions>
Critical: Facet regions are siblings of template regions at the same level, not nested inside them.
Required Metadata Structure
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
<flexiPageRegions>
<!-- Regions and components here -->
</flexiPageRegions>
<masterLabel>Page Label</masterLabel>
<template>
<name>flexipage:recordHomeTemplateDesktop</name>
</template>
<type>RecordPage</type>
<sobjectType>Object__c</sobjectType> <!-- RecordPage only -->
</FlexiPage>
Page Types:
RecordPage- requires<sobjectType>AppPage- no sobjectTypeHomePage- no sobjectType
Validation Checklist
Before deploying:
- Used CLI to bootstrap (don't start from scratch)
- All field references use
Record.{Field}format - Each fieldInstance has
fieldInstancePropertieswithuiBehavior - Each fieldInstance in own
<itemInstances>wrapper - Template regions use
<type>Region</type> - Component facets use
<type>Facet</type> - Property values with HTML/XML are manually encoded
- No
<mode>tags in regions - No
__csuffix in page names - Each Facet referenced by exactly one component property
Quick Reference: CLI Command
# RecordPage with fields
sf template generate flexipage \
--name Account_Custom_Page \
--template RecordPage \
--sobject Account \
--primary-field Name \
--secondary-fields Phone,Industry,AnnualRevenue \
--detail-fields Street,City,State,Name,Phone,Email
# AppPage
sf template generate flexipage \
--name Sales_Dashboard \
--template AppPage \
--label "Sales Dashboard"
# HomePage
sf template generate flexipage \
--name Custom_Home \
--template HomePage \
--description "Custom home for sales team"
All templates support:
--output-dir(default: current directory)--api-version(default: latest)--label(default: page name)--description