From sf-skills
Creates, modifies, or validates Salesforce Lightning pages (FlexiPages). Generates XML metadata for RecordPage, AppPage, and HomePage via CLI bootstrapping.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sf-skills:generating-flexipageThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill when you need to:
Use this skill when you need to:
CRITICAL: When creating NEW FlexiPages, you MUST ALWAYS start with the CLI template command. Never create FlexiPage XML from scratch - the CLI provides valid structure, proper regions, and correct component configuration that prevents deployment errors.
Generate Lightning pages (RecordPage, AppPage, HomePage) using CLI bootstrapping for component discovery and configuration.
MANDATORY FOR NEW PAGES: This step is NOT optional. Always use the CLI template command when creating a new FlexiPage. The CLI generates valid XML structure, proper regions, and correct metadata that prevents common deployment errors. Only skip this step if you're editing an existing FlexiPage file.
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
CRITICAL: If the sf template generate flexipage command fails, STOP.
sf plugins install templates
sf template generate flexipage commandDo NOT continue to Step 2 until the template command succeeds. The generated XML is required for the entire workflow.
RecordPage:
--sobject (e.g., Account, Custom_Object__c)--primary-field: Most important identifying field (e.g., Name)--secondary-fields: Record summary (recommended 4-6, max 12)--detail-fields: Full record details, including required fields (e.g., Name)AppPage:
HomePage:
Name (not FirstName/LastName), BillingAddress (not BillingStreet/BillingCity/BillingState), MailingAddress, etc. when availableName) in the --detail-fields parameter, even if they're also used in --primary-field or --secondary-fieldsRun a dry-run deployment of the entire project to validate the page and dependencies:
sf project deploy start --dry-run -d "force-app/main/default" --test-level NoTestRun --wait 10 --json
Critical: Fix any deployment errors before proceeding. The page must validate successfully.
MANDATORY: Stop after Step 2. Do not add components or edit the FlexiPage XML.
This applies even if the user requested:
What you CAN do:
What you CANNOT do:
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.
ALWAYS: Record.{FieldApiName}
NEVER: {ObjectName}.{FieldApiName}
<!-- Correct -->
<fieldItem>Record.Name</fieldItem>
<!-- Wrong -->
<fieldItem>Account.Name</fieldItem>
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.
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:
<itemInstances> wrapperfieldInstanceProperties with uiBehaviorRecord.{Field} formatEVERY identifier and region/facet name MUST be unique across the entire FlexiPage file.
Critical Rules:
<flexiPageRegions> blocks with the same <name><itemInstances><identifier> valueWrong - This WILL FAIL with duplicate name error:
<!-- First field section in detail tab -->
<flexiPageRegions>
<itemInstances>
<componentInstance>
<identifier>flexipage_property_details_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<name>detailTabContent</name> <!-- ❌ DUPLICATE NAME -->
<type>Facet</type>
</flexiPageRegions>
<!-- Second field section in detail tab -->
<flexiPageRegions>
<itemInstances>
<componentInstance>
<identifier>flexipage_pricing_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<name>detailTabContent</name> <!-- ❌ DUPLICATE NAME - DEPLOYMENT FAILS -->
<type>Facet</type>
</flexiPageRegions>
Correct - Combine itemInstances in ONE region:
<!-- Both field sections in same detail tab facet -->
<flexiPageRegions>
<itemInstances>
<componentInstance>
<identifier>flexipage_property_details_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<itemInstances>
<componentInstance>
<identifier>flexipage_pricing_fieldSection</identifier>
...
</componentInstance>
</itemInstances>
<name>detailTabContent</name> <!-- ✅ ONE REGION, MULTIPLE COMPONENTS -->
<type>Facet</type>
</flexiPageRegions>
When to combine vs separate:
detailTabContent vs relatedTabContent)Cause: Invalid field API name - field doesn't exist on the object or has incorrect spelling Fix: Use MCP tools or describe commands to discover valid fields, then update the field reference (see Field Selection Rules)
Cause: Used ObjectName.Field instead of Record.Field
Fix: Change to Record.{FieldApiName}
Cause: Multiple fieldInstances in one itemInstances
Fix: Each fieldInstance needs its own <itemInstances> wrapper
Cause: No uiBehavior specified
Fix: Add fieldInstanceProperties with uiBehavior
Cause: Facet defined but not referenced by any component
Fix: Remove Facet or reference it in a component property
Cause: Unencoded HTML/XML in property values
Fix: Manually encode <, >, &, ", ' in all <value> tags
Cause: Invalid page name (don't use __c suffix in page names)
Fix: Use "Volunteer_Record_Page" not "Volunteer__c_Record_Page"
Cause: Added <mode> tag to region
Fix: Remove <mode> tags - they're not needed for standard regions
CRITICAL: Before generating ANY new identifier or facet name, follow the rules in section 5 of "Critical XML Rules" above.
Identifier Generation Algorithm:
1. Extract ALL existing <identifier> AND <name> 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:
relatedList_contacts_1relatedList_contacts_2richText_header_1fieldSection_details_1Facet Naming - Two Patterns:
Named facets (for major content areas):
detailTabContent (detail tab content)maintabs (main tab container)sidebartabs (sidebar tab container)UUID facets (for internal structure):
Facet-{8hex}-{4hex}-{4hex}-{4hex}-{12hex}Facet-66d5a4b3-bf14-4665-ba75-1ceaa71b2cdeWhen adding components to existing files:
<itemInstances> to that existing region (see section 5 above for details)Parse regions from file - don't hardcode names. Templates vary:
flexipage:recordHomeTemplateDesktop → header, main, sidebarruntime_service_fieldservice:... → header, main, footerDefault 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>
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>
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.
Use for: Displaying fields in columns. Structure: Three-level nesting:
<componentInstanceProperties>
<name>columns</name>
<value>Facet-{uuid}</value>
</componentInstanceProperties>
Component name: flexipage:richText
Use for: Displaying HTML-formatted rich text content with support for text formatting, headings, lists, tables, images, links, forms, and multimedia elements. Preserves styling and layout. Escape all special characters in the default text.
Location: Can be used in any region on any page type (Home, Record, App, Community pages).
CLI generates the component directly without nested structures.
User: "Add a rich text component to force-app/.../Account_Record_Page.flexipage-meta.xml"
Structure: Single-level component (no facets):
XML Structure Example:
<itemInstances>
<componentInstance>
<componentInstanceProperties>
<name>decorate</name>
<value>true</value>
</componentInstanceProperties>
<componentName>flexipage:richText</componentName>
<identifier>flexipage_richText</identifier>
</componentInstance>
</itemInstances>
Identifier Pattern: flexipage_richText or flexipage_richText_{sequence}
<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 sobjectTypeBefore deploying:
<identifier> values anywhere in file<name> values in <flexiPageRegions><itemInstances>, NOT separate regions with same nameRecord.{Field} formatfieldInstanceProperties with uiBehavior<itemInstances> wrapper<type>Region</type><type>Facet</type><mode> tags in regions__c suffix in page names# 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)--descriptionnpx claudepluginhub ccmalcom/sf-skills-plugin --plugin sf-skillsBuilds Salesforce Lightning Experience apps from natural language by generating all required metadata types (objects, fields, pages, tabs, security) in dependency order.
Creates, updates, and deploys Power Apps generative pages for model-driven apps using React 17, TypeScript, Fluent UI V9, and PAC CLI. Useful for building or updating pages in Power Apps.
Adds robots.txt, sitemap.xml, meta tags (title, description, Open Graph), and favicon to Power Pages code sites after /create-site. Improves crawlability and search visibility.