Loading...
Loading...
OmniStudio FlexCard creation and validation with 130-point scoring. Use when building at-a-glance UI cards, configuring data source bindings to Integration Procedures, or reviewing existing FlexCard definitions for accessibility and performance. TRIGGER when: user creates FlexCards, configures data sources, designs card layouts, or asks about OmniUiCard metadata. DO NOT TRIGGER when: building OmniScripts (use building-omnistudio-omniscript), creating Integration Procedures (use building-omnistudio-integration-procedure), or analyzing dependencies (use analyzing-omnistudio-dependencies).
npx skill4agent add forcedotcom/sf-skills building-omnistudio-flexcardOmniUiCardbuilding-omnistudio-omniscriptbuilding-omnistudio-integration-procedureanalyzing-omnistudio-dependenciesdeploying-metadata| Need | Document | Description |
|---|---|---|
| Best practices | references/best-practices.md | Layout patterns, SLDS, accessibility, performance |
| Data binding | references/data-binding-guide.md | IP sources, field mapping, conditional rendering |
analyzing-omnistudio-dependencies → building-omnistudio-datamapper → building-omnistudio-integration-procedure → building-omnistudio-omniscript → building-omnistudio-flexcard (you are here)| Insight | Detail |
|---|---|
| Configuration fields | |
| Data source binding | Data sources bind to Integration Procedures for live data; the IP must be active and deployed before the FlexCard can retrieve data |
| Child card embedding | FlexCards can embed other FlexCards as child cards, enabling composite layouts with shared or independent data sources |
| OmniScript launching | FlexCards can launch OmniScripts via action buttons, passing context data from the card's data source into the OmniScript's input |
| Designer virtual object | The FlexCard Designer uses |
| Question | Why It Matters |
|---|---|
| What is the card's purpose? | Determines layout type and data density |
| Which data sources are needed? | Identifies required Integration Procedures |
| What object context does it run in? | Determines record-level vs. list-level display |
| What actions should the card expose? | Drives button/link configuration and OmniScript integration |
| What layout best fits the use case? | Single card, list, tabbed, or flyout |
| Are there conditional display rules? | Fields or sections that appear/hide based on data values |
references/best-practices.md| Layout Type | Use Case | Description |
|---|---|---|
| Single Card | Record summary | One card displaying fields from a single record |
| Card List | Related records | Repeating cards bound to an array data source |
| Tabbed Card | Multi-context | Multiple states displayed as tabs within one card |
| Flyout Card | Detail on demand | Expandable detail panel triggered from a summary card |
FlexCard → Data Source (type: IntegrationProcedure)
→ IP Name + Input Mapping
→ Response Field Mapping → Card Elements{datasource.fieldName}{recordId}| Action Type | Purpose | Configuration |
|---|---|---|
| Launch OmniScript | Start a guided process | OmniScript Type + SubType, pass context params |
| Navigate | Go to record or URL | Record ID or URL template with merge fields |
| Custom Action | Platform event, LWC, etc. | Custom action handler with payload mapping |
references/data-binding-guide.mdreferences/scoring-rubric.mddeploying-metadata--dry-runOmniUiCardsf project deploy startCannot find OmniIntegrationProcedureEntity not found| Scenario | What to Verify |
|---|---|
| Populated data | All fields render correctly, merge fields resolve |
| Empty data | Empty-state message displays, no broken merge fields |
| Error state | Graceful handling when IP returns an error or times out |
| Multi-record | Card list renders correct number of items, pagination works |
| Action buttons | OmniScript launches with correct pre-populated data |
| Conditional fields | Visibility rules toggle correctly based on data values |
| Mobile | Card layout adapts to smaller viewport widths |
| Anti-Pattern | Why It's Wrong | Correct Approach |
|---|---|---|
| Referencing non-existent IP data sources | Card fails to load data at runtime | Verify IP exists and is active before binding |
| Hardcoded colors in styles | Breaks SLDS theming and dark mode | Use SLDS design tokens and CSS custom properties |
| Missing accessibility attributes | Fails WCAG compliance | Add |
| Excessive nested child cards | Performance degrades with deep nesting | Limit to 2 levels of nesting; flatten where possible |
| Ignoring empty states | Broken UI when data source returns no records | Configure explicit empty-state messaging |
| Hardcoded record IDs | Card breaks across environments | Use merge fields and context-driven parameters |
| Category | Points | Criteria |
|---|---|---|
| Design & Layout | 25 | Appropriate layout type, logical field grouping, responsive design, consistent spacing, clear visual hierarchy |
| Data Binding | 20 | Correct IP references, proper merge field syntax, input parameter mapping, multi-source coordination |
| Actions & Navigation | 20 | Action buttons configured correctly, OmniScript launch params mapped, navigation targets valid, action labels descriptive |
| Styling | 20 | SLDS tokens used (no hardcoded colors), consistent typography, proper use of card/tile patterns, dark mode compatible |
| Accessibility | 15 | |
| Testing | 15 | Verified with populated data, empty state, error state, multi-record scenario, and mobile viewport |
| Performance | 15 | Data source calls minimized, child card nesting limited (max 2 levels), no redundant IP calls, lazy loading for non-visible states |
references/scoring-rubric.mdscripts/flexcard-commands.sh<org><Name>DataSourceConfigOmniUiCardPropertySetConfigIMPORTANT: There is NOfield onDefinitionin Core namespace. UseOmniUiCardfor data sources andDataSourceConfigfor layout.PropertySetConfig
assets/omni-ui-card.jsonDataSourceConfig| Type | | When to Use |
|---|---|---|
| Integration Procedure | | Primary pattern; calls an IP for live data |
| SOQL | | Direct query (use sparingly; prefer IP for abstraction) |
| Apex Remote | | Custom Apex class invocation |
| REST | | External API call via Named Credential |
| Custom | | Custom data provider (pass JSON body directly) |
IP Response: FlexCard Merge Field:
───────────── ─────────────────────
{ "Name": "Acme Corp" } → {Name}
{ "Account": { → {Account.Name}
"Name": "Acme Corp"
}
}
{ "records": [ → {records[0].Name} (single)
{ "Name": "Acme" } or iterate with Card List layout
]
}| Context Variable | Source | Example |
|---|---|---|
| Current record page | Pass to IP to query related data |
| Running user | Filter data by current user |
| URL parameter or parent card | Pass from parent FlexCard or URL |
| Skill | Relationship to building-omnistudio-flexcard |
|---|---|
| building-omnistudio-integration-procedure | Build the IP data sources that FlexCards consume |
| building-omnistudio-omniscript | Build the OmniScripts that FlexCard action buttons launch |
| building-omnistudio-datamapper | Build DataRaptors/DataMappers that IPs use under the hood |
| analyzing-omnistudio-dependencies | Analyze dependency chains across FlexCards, IPs, and OmniScripts |
| deploying-metadata | Deploy FlexCard metadata along with upstream dependencies |
| generating-lwc-components | Build custom LWC components embedded within FlexCards |
| Scenario | Handling |
|---|---|
| Empty data | Configure an explicit empty-state with a user-friendly message; do not show raw "No data" or blank card |
| Error states | Display a meaningful error message when the IP data source fails; log the error for debugging |
| Mobile responsiveness | Use single-column layout for mobile; avoid horizontal scrolling; test at 320px viewport width |
| Long text values | Truncate with ellipsis and provide a flyout or tooltip for full text |
| Large record sets | Use card list with pagination; limit initial load to 10-25 records |
| Null field values | Use conditional visibility to hide fields with null values rather than showing empty labels |
| Mixed data freshness | When multiple data sources have different refresh rates, display a "last updated" indicator |
| Factor | FlexCard | LWC |
|---|---|---|
| Build method | Declarative (drag-and-drop) | Code (JS, HTML, CSS) |
| Data binding | Integration Procedure merge fields | Wire service, Apex, GraphQL |
| Best for | At-a-glance information display | Complex interactive UIs |
| Testing | Manual + data state verification | Jest unit tests + manual |
| Customization | Limited to OmniStudio framework | Full platform flexibility |
| Reuse | Embed as child cards | Import as child components |
| When to choose | Standard card layouts with IP data | Custom behavior, animations, complex state |
sfsf project deploy startscripts/flexcard-commands.shomnistudio__OmniUiCardsfdx-project.jsonscripts/flexcard-commands.shsf api request rest --method POST --body @file.jsonNameVersionNumberOmniUiCardTypeChildDataSourceConfigPropertySetConfigsf data create record --valuesIsActive=trueassets/omni-ui-card.jsonOmniUiCardDataSourceConfigPropertySetConfig| File | When to read |
|---|---|
| Phase 3 — Generation: OmniUiCard record template including DataSourceConfig JSON structure |
| Phase 2 — Layout patterns, SLDS compliance, accessibility requirements, and performance guidance |
| Phase 2-3 — Data source types, merge field syntax, input parameter mapping, and multi-source coordination |
| Phase 3 — Full per-criterion breakdown of all 7 scoring categories (130 points) |
| Phase 4 — All CLI commands for querying, retrieving, and deploying FlexCard metadata |