Merge branch 'main' into main

This commit is contained in:
thrylokya 2026-03-24 01:41:36 +05:30 committed by GitHub
commit 9bb0d37467
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 1502 additions and 1976 deletions

View File

@ -58,29 +58,24 @@ jobs:
output-file: "CHANGELOG.md"
git-push: "false"
- name: Report validate-skills status on release commit
- name: Push release commit to main
if: ${{ steps.changelog.outputs.skipped == 'false' }}
env:
GH_TOKEN: ${{ secrets.IDEE_GH_TOKEN }}
run: |
SHA=$(git rev-parse HEAD)
TEMP_BRANCH="release-$(date +%s)"
# Push commit to a temp branch so the SHA exists on the remote
git push origin "$SHA:refs/heads/$TEMP_BRANCH"
# Report the required status check on the now-visible commit
gh api "repos/${{ github.repository }}/statuses/$SHA" \
-f state=success \
-f context=validate-skills \
-f description="Validated in release workflow"
- name: Verify tag does not already exist
if: ${{ steps.changelog.outputs.skipped == 'false' }}
run: |
TAG="${{ steps.changelog.outputs.tag }}"
if git ls-remote --tags origin | grep -q "refs/tags/$TAG$"; then
echo "::error::Tag $TAG already exists on remote. Delete it first if re-releasing: git push --delete origin $TAG"
exit 1
fi
- name: Push release commit and tag
if: ${{ steps.changelog.outputs.skipped == 'false' }}
run: git push origin main --follow-tags
# Push to main (status check is now satisfied)
git push origin main --follow-tags
# Clean up temp branch
git push origin --delete "$TEMP_BRANCH" || true
- name: Create Github Release
id: release

View File

@ -1,3 +1,18 @@
# [1.3.0](https://github.com/forcedotcom/afv-library/compare/1.2.0...1.3.0) (2026-03-23)
### Bug Fixes
* resolve release workflow branch protection failure @W-21658353@ ([#80](https://github.com/forcedotcom/afv-library/issues/80)) ([5d3f085](https://github.com/forcedotcom/afv-library/commit/5d3f085ad67f10be3a3a20d7dc0142a000dbd957))
### Features
* Add switching-org skill @W-21436488@ ([#74](https://github.com/forcedotcom/afv-library/issues/74)) ([5c40e3b](https://github.com/forcedotcom/afv-library/commit/5c40e3b63ed81e9559a4d64c82f112a94c5c2566))
* syncing webapp skills sync to afv @W-21338965@ ([#57](https://github.com/forcedotcom/afv-library/issues/57)) ([9ba0641](https://github.com/forcedotcom/afv-library/commit/9ba064174a714e487c683b986c3c6e08d478b784))
# [1.2.0](https://github.com/forcedotcom/afv-library/compare/1.1.0...1.2.0) (2026-03-19)

View File

@ -1,6 +1,6 @@
{
"name": "@salesforce/afv-skills",
"version": "1.2.0",
"version": "1.3.0",
"description": "Salesforce skills for Agentforce Vibes",
"license": "CC-BY-NC-4.0",
"files": [

View File

@ -1,42 +1,88 @@
# Rule: Salesforce Metadata Generation
## Objective
Enforce: **skill load -> API context -> file generation** for all Salesforce metadata.
## Constraints
1. **Never write** without both: metadata type skill loaded AND context tools from `salesforce-api-context` MCP server called for that type.
2. **One type at a time** - finish one type before starting the next
3. **One type per API call** - do not batch types when calling MCP tools
4. **Child types need their own context** - if adding any child metadata inside a parent metadata's file, treat the child metadata seperately; don't rely on the parent's schema for creating child metadata
5. **Max one clarifying question** before starting
1. **Never write** without a loaded metadata type skill for that type.
2. **One type at a time** - complete the full cycle for the current type before moving to the next type.
3. **Always attempt `salesforce-api-context` MCP** for each type before writing; if it is unavailable after a real attempt, proceed with the loaded skill only.
4. **Child types need their own API context response** - if adding child metadata inside a parent metadata file, load the child metadata skill and use `salesforce-api-context` MCP for each child type separately; do not rely on the parent's schema or API context response for child metadata creation. The same fallback in constraint 3 applies.
5. **Max one clarifying question** before starting.
6. **Do not call `execute_metadata_action` unless a skill instructs you to do so.**
## Workflow
## Skill Selection
### Step 1: Metadata Loop - Execute for Each Type
For each type, execute loop below
- Search available skills and load the best-matching app-level skill first when the request asks for a Lightning app, end-to-end solution, or a business app spanning multiple metadata types.
- Search available skills and load the best-matching per-type metadata skill first when the request targets individual metadata components.
## Initial Gate
Never create files or generate metadata before completing skill selection.
1. Determine whether the request is app-level or metadata-type-level.
2. Search available skills for the request and identify the best-matching candidate skill.
3. If the request is app-level, load the best-matching app-level skill by reading its contents and use it to identify metadata types and dependency order.
4. If the request is metadata-type-level, identify the target metadata type and the best-matching per-type metadata skill for that type. Do not treat skill selection as the per-type skill-load step.
5. Confirm skill selection with:
`intent=<app|type> selected_skill=<exact-skill-name|none> skill_selection=complete|pending`
6. Set `skill_selection=complete` only after the exact selected skill name has been identified and recorded.
7. Print this exact skill-selection status line in the chat before proceeding.
Do not continue until `skill_selection=complete` and `selected_skill=<exact-skill-name|none>` are recorded.
## Per-Type Loop (a-e)
For each metadata type in scope, whether identified by an app-level skill or requested directly, execute steps a through e below one metadata type at a time. Do not create or modify files for the current metadata type, and do not move to the next metadata type, until steps a through e are complete.
**a. Load Skill**
- Load the metadata type skill once (not per record)
- Search available skills for the best-matching skill for the current metadata type and load it by reading its SKILL.md.
- Record `selected_skill=<exact-skill-name|none>` for the current metadata type before proceeding.
- Load once per type, not per record.
- If no skill exists after a real search, stop and ask for guidance instead of writing without a skill.
**b. Get entity context**
- Use these tools from `salesforce-api-context` MCP server for entity context.
- `get_metadata_type_sections`
- `get_metadata_type_context`
- `get_metadata_type_fields`
- `get_metadata_type_fields_properties`
- `search_metadata_types`
**b. Use `salesforce-api-context` MCP**
- Use one or more of these tools as required:
- `get_metadata_type_sections`
- `get_metadata_type_context`
- `get_metadata_type_fields`
- `get_metadata_type_fields_properties`
- `search_metadata_types`
- Attempt API context for every type before writing.
- Record which tools were called for the current metadata type before proceeding.
- If API context is unavailable after a real attempt, record that state and continue with the loaded skill only.
- Treat templates, generators, pipelines, and CLI bootstraps as implementation aids, not as replacements for this gate.
**c. Pre-Write Gate**
- Before EVERY write: confirm `selected_skill=<exact-skill-name>` is recorded and that skill is loaded for this type.
- Before EVERY write: confirm `mcp_tools=<tool-list>` is recorded for this type, or confirm `mcp=unavailable` after a real attempt.
- If `selected_skill=none` or the skill is missing -> stop.
- If `mcp_tools=none` and `mcp` is not `unavailable` -> stop and call MCP now.
### Step 2. Verify deployment
```bash
sf project deploy start --dry-run -d "force-app/main/default" --target-org <alias> --test-level NoTestRun --wait 10 --json
```
On failure: attempt to fix the errors and re-run, retrying up to a maximum of 3 times until it succeeds.
**d. Generate Files**
- Use skill constraints + API context when available.
- Use skill constraints only when API context was unavailable after a real attempt.
- Generate all records for this type now.
**e. Checkpoint**
- Record:
`type=<metadata-type> selected_skill=<exact-skill-name|none> skill=complete|pending mcp=complete|pending|unavailable mcp_tools=<tool-list|none>`
- Skill loaded? API context called or unavailable after a real attempt? All files written?
- Only proceed to the next type when all are true.
## Anti-Patterns
| Don't | Why | Do |
|-------|-----|-----|
| Reload skill per record | Wastes tokens | Load once per type |
| Skip metadata skills | Missing platform constraints | Load skill for every type |
| Ask 3+ questions | Token waste | Max 1 question |
| Batch types in calls to MCP tools | Violates constraint | One type per call |
| Never write without loading the metadata skill | Missing platform constraints | Search for and load the skill before any write |
| Never mark `skill_selection=complete` without `selected_skill=<exact-skill-name|none>` | Fake gate completion | Record the exact selected skill before continuing |
| Never treat skill selection as skill loading | Fake gate completion | Perform the actual per-type skill load in step a |
| Never skip the Initial Gate | Sequence breach | Complete skill selection before any generation |
| Never reload a skill per record | Wastes tokens | Load once per type |
| Never skip the API context attempt for any type | No schema for those types | Attempt API context for EVERY type |
| Never write using API context alone without a loaded skill | Missing platform constraints | Stop and ask for guidance when no skill exists |
| Never write without recorded `mcp_tools` or `mcp=unavailable` | No evidence of MCP gate completion | Record MCP tool usage before any write |
| Never ask more than 1 clarifying question | Token waste | Max 1 question |
| Never skip any gate in the loop (skill load, API context, pre-write, checkpoint) | Wrong artifacts | Follow all mandatory gates in the loop (a-e) |
| Never write with a missing checkpoint | Aware violation | Stop and complete missing step |

View File

@ -2,9 +2,9 @@
"type": "experience__camaAppMetadata",
"title": "App Metadata",
"contentBody": {
"version": "1.0.0",
"name": "Homestead",
"description": "Mobile application for managing property rentals, tenant information, lease agreements, and maintenance requests.",
"version": "1.0.0",
"url": "http://login.test1.pc-rnd.salesforce.com/",
"templateID": "1",
"tabs": [
@ -12,30 +12,33 @@
"id": "home",
"label": "Home",
"icon": "house.fill",
"screen": "homeScreen"
"screenAPIName": "uem_homesteadHome"
},
{
"id": "tenants",
"label": "Tenants",
"icon": "person.2.fill",
"screen": "tenantsScreen"
},
{
"id": "properties",
"label": "Properties",
"icon": "building.2.fill",
"screen": "propertiesScreen"
"id": "calendar",
"label": "Calendar",
"icon": "calendar",
"screenAPIName": "calendar"
}
],
"toolbarActions": {
"notifications": false,
"search": false,
"agentforce": false
"search": false
},
"theme": {
"accentColor": "#9400D3",
"primaryColor": "#000000",
"secondaryColor": "#B3B3B3"
"colors": {
"accent1": "#7526E3",
"accent2": "#7526E3",
"accentContainer1": "#7526E3",
"accentContainer2": "#1F1A30",
"onSurface1": "#181818",
"onSurface2": "#444444",
"onSurface3": "#747474"
},
"cornerRadius": {
"radiusBorderCircle": "12"
}
}
}
},
"urlName": "app-metadata"
}

View File

@ -3,6 +3,7 @@
"title": "Build Metadata",
"contentBody": {
"BiometricOptIn": false,
"NotificationOptIn": false
}
"NotificationOptIn": true
},
"urlName": "build-metadata"
}

View File

@ -1,5 +0,0 @@
{
"apiName": "rentalApp",
"type": "experience__camaECDefinition",
"path": "rentalApp"
}

View File

@ -1,5 +0,0 @@
{
"type": "experience__camaECDefinition",
"title": "CAMA EC Definition",
"contentBody": {}
}

View File

@ -0,0 +1,5 @@
{
"apiName": "calendar",
"type": "experience__camaScreen",
"path": "calendar"
}

View File

@ -0,0 +1,26 @@
{
"type": "experience__camaScreen",
"title": "Calendar",
"contentBody": {
"view": {
"definition": "calendar/root",
"properties": {},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "calendar/home",
"properties": {},
"regions": {}
}
]
}
}
},
"target": "native__calendar",
"apiName": "calendar",
"id": "calendar-home-001"
},
"urlName": "calendar"
}

View File

@ -0,0 +1,5 @@
{
"apiName": "home",
"type": "experience__camaScreen",
"path": "home"
}

View File

@ -0,0 +1,742 @@
{
"type": "experience__camaScreen",
"title": "Home",
"contentBody": {
"view": {
"definition": "builder/screen",
"name": "Tenant App",
"properties": {},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/container",
"properties": {
"padding": "0",
"backgroundColor": "$colors.accentContainer2",
"gap": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/column",
"properties": {
"padding": "$spacing.spacing4",
"gap": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/box",
"properties": {
"padding": {
"top": "$spacing.spacing4"
}
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Good evening, Maria",
"style": "titlesFontScale4Regular",
"color": "$colors.onSurfaceInverse1"
},
"regions": {}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {
"backgroundColor": "$colors.surfaceContainer1",
"padding": "$spacing.spacing4",
"borderColor": null
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/row",
"properties": {
"gap": "spaceBetween"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Latest news",
"style": "titlesFontScale3Regular",
"color": "$colors.onSurface2"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "See all",
"style": "bodyFontScale1Regular",
"color": "$colors.accent1"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/horizontalScroll",
"properties": {
"gap": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2",
"alignment": "start"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/box",
"properties": {
"radius": "$radius.radiusBorder2",
"width": "fill"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/image",
"properties": {
"source": {
"url": "https://picsum.photos/seed/community/220/140"
},
"alternativeText": "Community Park",
"width": "220",
"height": "140"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/text",
"properties": {
"text": "Community Park opens",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "Mar 1, 2026",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2",
"alignment": "start"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/box",
"properties": {
"radius": "$radius.radiusBorder2",
"width": "fill"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/image",
"properties": {
"source": {
"url": "https://picsum.photos/seed/treadmills/220/140"
},
"alternativeText": "New treadmills",
"width": "220",
"height": "140"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/text",
"properties": {
"text": "New treadmills!",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "Feb 12, 2026",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2",
"alignment": "start"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/box",
"properties": {
"radius": "$radius.radiusBorder2",
"width": "fill"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/image",
"properties": {
"source": {
"url": "https://picsum.photos/seed/pool/220/140"
},
"alternativeText": "Pool hours extended",
"width": "220",
"height": "140"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/text",
"properties": {
"text": "Pool hours extended",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "Feb 28, 2026",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {
"borderColor": "$colors.border1",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/row",
"properties": {
"gap": "$spacing.spacing10",
"alignment": "center"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/progressRing",
"properties": {
"value": 85,
"size": "large",
"showProgressText": true
},
"regions": {}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2",
"alignment": "start"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Lease progress",
"style": "titlesFontScale3Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "Renewal period",
"style": "bodyFontScaleBaseRegular",
"color": "$colors.onSurface2"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "ends Mar 1, 2026",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2"
},
"regions": {}
},
{
"definition": "ui/button",
"properties": {
"label": "Continue",
"variant": "brandOutline"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/text",
"properties": {
"text": "Recommended for you",
"style": "titlesFontScale3Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing3"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/card",
"properties": {
"borderColor": "$colors.border1",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/row",
"properties": {
"gap": "$spacing.spacing3",
"alignment": "center"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/icon",
"properties": {
"iconName": "utility:email",
"size": "large",
"color": "$colors.success1"
},
"regions": {}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing1"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "3 packages ready for pickup",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "Locker #104 | Code:8829",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {
"borderColor": "$colors.border1",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/row",
"properties": {
"gap": "$spacing.spacing3",
"alignment": "center"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/icon",
"properties": {
"iconName": "utility:favorite",
"size": "large",
"color": "$colors.warning1"
},
"regions": {}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing1"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Rate your technician",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "How was your recent dishwasher fix?",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {
"borderColor": "$colors.border1",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/row",
"properties": {
"gap": "$spacing.spacing3",
"alignment": "center"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/icon",
"properties": {
"iconName": "utility:list",
"size": "large",
"color": "$colors.information1"
},
"regions": {}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2",
"alignment": "start"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Complete Move-In Inspection",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "You've been here 30 days. How is everything?",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/button",
"properties": {
"label": "Take a survey",
"variant": "brandOutline"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {
"borderColor": "$colors.border1",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/row",
"properties": {
"gap": "$spacing.spacing3",
"alignment": "center"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/icon",
"properties": {
"iconName": "utility:event",
"size": "large",
"color": "$colors.accent1"
},
"regions": {}
},
{
"definition": "ui/column",
"properties": {
"gap": "$spacing.spacing2",
"alignment": "start"
},
"regions": {
"components": {
"name": "components",
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Check out your perks",
"style": "bodyFontScale1Semibold",
"color": "$colors.onSurface1",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "Schedule a personal tour of amenities",
"style": "bodyFontScaleNeg1Regular",
"color": "$colors.onSurface2",
"textAlign": "start"
},
"regions": {}
},
{
"definition": "ui/button",
"properties": {
"label": "Book a tour",
"variant": "brandOutline"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/footer",
"properties": {
"label": "More"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
}
]
}
}
}
]
}
}
},
"target": "native__homesteadHome",
"apiName": "uem_homesteadHome",
"id": "homestead-app-home"
},
"urlName": "home"
}

View File

@ -1,5 +0,0 @@
{
"apiName": "homeScreen",
"type": "experience__camaScreen",
"path": "homeScreen"
}

View File

@ -1,489 +0,0 @@
{
"type": "experience__camaScreen",
"title": "Home Screen",
"contentBody": {
"view": {
"definition": "homestead/HomeScreen",
"properties": {
"pullToRefresh": true
},
"regions": {
"components": {
"components": [
{
"definition": "ui/container",
"properties": {
"padding": "$spacing.spacing4",
"backgroundColor": "$colors.surface2"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/card",
"properties": {},
"regions": {
"components": {
"components": [
{
"definition": "ui/column",
"properties": {
"width": "fill",
"height": "fill",
"alignment": "start",
"gap": "$spacing.spacing4",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Today",
"style": "titlesFontScale4Semibold",
"color": "$colors.onSurface1"
},
"regions": {}
},
{
"definition": "ui/text",
"properties": {
"text": "You have no event.",
"color": "$colors.onSuccess1",
"style": "bodyFontScale2Regular"
},
"regions": {}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {},
"regions": {
"components": {
"components": [
{
"definition": "ui/column",
"properties": {
"width": "fill",
"height": "fill",
"alignment": "start",
"gap": "$spacing.spacing4",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Upcoming",
"style": "titlesFontScale4Semibold",
"color": "$colors.onSurface1"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "123 Oak Street",
"subtitle": "Inspection on 01/08/2026"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/nothing"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Scheduled",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "456 Maple Avenue",
"subtitle": "Lease Signing on 01/10/2026"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/nothing"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Scheduled",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "789 Pine Road",
"subtitle": "Maintenance on 01/15/2026"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/nothing"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Requested",
"variant": "error"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "321 Elm Street",
"subtitle": "Rent Collection on 01/20/2026"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/nothing"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Scheduled",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Community Center",
"subtitle": "HOA Meeting on 01/22/2026"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/nothing"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Proposed",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "555 Cedar Lane",
"subtitle": "Background Check"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/nothing"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "In Progress",
"variant": "warning"
},
"regions": {}
}
]
}
}
}
]
}
}
},
{
"definition": "ui/card",
"properties": {},
"regions": {
"components": {
"components": [
{
"definition": "ui/column",
"properties": {
"width": "fill",
"height": "fill",
"alignment": "start",
"gap": "$spacing.spacing4",
"padding": "$spacing.spacing4"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/text",
"properties": {
"text": "Tenants",
"style": "titlesFontScale4Semibold",
"color": "$colors.onSurface1"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Sarah Johnson",
"subtitle": "456 Maple Avenue, Apt 5"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Michael Chen",
"subtitle": "789 Pine Road"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Overdue",
"variant": "error"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Emily Davis",
"subtitle": "321 Elm Street, Unit 5B"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Robert Williams",
"subtitle": "555 Cedar Lane"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Jessica Martinez",
"subtitle": "123 Oak Street, Unit 3C"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Moved Out",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "David Lee",
"subtitle": "456 Maple Avenue, Apt 2"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Signed",
"variant": "lightest"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
}
]
}
}
},
"target": "native__homesteadHome",
"apiName": "uem_homesteadHome"
}
}

View File

@ -1,5 +0,0 @@
{
"apiName": "propertiesScreen",
"type": "experience__camaScreen",
"path": "propertiesScreen"
}

View File

@ -1,565 +0,0 @@
{
"type": "experience__camaScreen",
"title": "Properties Screen",
"contentBody": {
"view": {
"definition": "homestead/PropertiesScreen",
"properties": {
"pullToRefresh": true
},
"regions": {
"components": {
"components": [
{
"definition": "ui/container",
"properties": {
"padding": "$spacing.spacing4",
"backgroundColor": "$colors.surface2"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/card",
"properties": {},
"regions": {
"components": {
"components": [
{
"definition": "ui/baseRow",
"properties": {
"title": "Oak Street Apartments",
"subtitle": "123 Oak Street"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Maple Avenue Complex",
"subtitle": "456 Maple Avenue"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Partial",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Pine Road House",
"subtitle": "789 Pine Road"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Vacant",
"variant": "lightest"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Cedar Lane Condos",
"subtitle": "555 Cedar Lane"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Elm Street Tower",
"subtitle": "321 Elm Street"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Partial",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Birch Boulevard Villa",
"subtitle": "234 Birch Boulevard"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Willow Way Estates",
"subtitle": "890 Willow Way"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Vacant",
"variant": "lightest"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Sunset Plaza",
"subtitle": "567 Sunset Drive"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Riverside Apartments",
"subtitle": "678 River Road"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Partial",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Lakeside Manor",
"subtitle": "901 Lake Avenue"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Mountain View Heights",
"subtitle": "112 Mountain Road"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Maintenance",
"variant": "error"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Harbor Point Lofts",
"subtitle": "445 Harbor Street"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Partial",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Garden Terrace",
"subtitle": "223 Garden Lane"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Park Place Residences",
"subtitle": "334 Park Avenue"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Vacant",
"variant": "lightest"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Hillside Court",
"subtitle": "778 Hill Street"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Downtown Tower",
"subtitle": "990 Main Street"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Partial",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Bayside Commons",
"subtitle": "101 Bay Road"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Full",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Meadow Brook Village",
"subtitle": "212 Meadow Lane"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/home",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Maintenance",
"variant": "error"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
}
]
}
}
},
"target": "native__homesteadProperties",
"apiName": "uem_homesteadProperties"
}
}

View File

@ -1,5 +0,0 @@
{
"apiName": "tenantsScreen",
"type": "experience__camaScreen",
"path": "tenantsScreen"
}

View File

@ -1,478 +0,0 @@
{
"type": "experience__camaScreen",
"title": "Tenants Screen",
"contentBody": {
"view": {
"definition": "homestead/TenantsScreen",
"properties": {
"pullToRefresh": true
},
"regions": {
"components": {
"components": [
{
"definition": "ui/container",
"properties": {
"padding": "$spacing.spacing4",
"backgroundColor": "$colors.surface2"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/card",
"properties": {},
"regions": {
"components": {
"components": [
{
"definition": "ui/baseRow",
"properties": {
"title": "Sarah Johnson",
"subtitle": "456 Maple Avenue, Apt 5"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Michael Chen",
"subtitle": "789 Pine Road"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Overdue",
"variant": "error"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Emily Davis",
"subtitle": "321 Elm Street, Unit 5B"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Robert Williams",
"subtitle": "555 Cedar Lane"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Jessica Martinez",
"subtitle": "123 Oak Street, Unit 3C"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Moved Out",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "David Lee",
"subtitle": "456 Maple Avenue, Apt 2"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Signed",
"variant": "lightest"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Amanda Thompson",
"subtitle": "789 Pine Road, Unit 7A"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Christopher Garcia",
"subtitle": "321 Elm Street, Apt 8"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Overdue",
"variant": "error"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Nicole Anderson",
"subtitle": "555 Cedar Lane, Unit 12B"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "James Wilson",
"subtitle": "123 Oak Street, Apt 1A"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Pending",
"variant": "warning"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Rachel Brown",
"subtitle": "456 Maple Avenue, Unit 9C"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Kevin Taylor",
"subtitle": "789 Pine Road, Apt 4B"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Signed",
"variant": "lightest"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Stephanie Miller",
"subtitle": "321 Elm Street, Unit 6D"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Brian Martinez",
"subtitle": "555 Cedar Lane, Apt 10A"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Overdue",
"variant": "error"
},
"regions": {}
}
]
}
}
},
{
"definition": "ui/baseRow",
"properties": {
"title": "Laura Rodriguez",
"subtitle": "123 Oak Street, Unit 11B"
},
"regions": {
"components": {
"components": [
{
"definition": "ui/utilityIcon",
"properties": {
"iconName": "utility/user",
"size": "small"
},
"regions": {}
},
{
"definition": "ui/badge",
"properties": {
"label": "Paid",
"variant": "success"
},
"regions": {}
}
]
}
}
}
]
}
}
}
]
}
}
}
]
}
}
},
"target": "native__homesteadTenants",
"apiName": "uem_homesteadTenants"
}
}

View File

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<DigitalExperienceBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<digitalExperienceFolderShares/>
<label>CAMA Rental App</label>
<modules>
<module>
<fullyQualifiedName>sfdc_cms__collection</fullyQualifiedName>
<status>ENABLED</status>
</module>
<module>
<fullyQualifiedName>sfdc_cms__media</fullyQualifiedName>
<status>ENABLED</status>
</module>
</modules>
</DigitalExperienceBundle>

View File

@ -0,0 +1,5 @@
{
"apiName" : "languages",
"type" : "sfdc_cms__languageSettings",
"path" : "_settings"
}

View File

@ -0,0 +1,14 @@
{
"type" : "sfdc_cms__languageSettings",
"title" : "LanguageContent",
"contentBody" : {
"languages" : [ {
"locale" : "en_US",
"label" : "English (US)",
"isActive" : true,
"isAuthoringOnly" : false
} ],
"defaultLocale" : "en_US"
},
"urlName" : "languagecontent"
}

View File

@ -53,7 +53,7 @@ Applies to:
Reject:
- backslashes
- leading `/` or `\`
- leading `\`
- `..` segments
- null or control characters
- globs: `*`, `?`, `**`

View File

@ -53,7 +53,7 @@ Applies to:
Reject:
- backslashes
- leading `/` or `\`
- leading `\`
- `..` segments
- null or control characters
- globs: `*`, `?`, `**`

View File

@ -53,7 +53,7 @@ Applies to:
Reject:
- backslashes
- leading `/` or `\`
- leading `\`
- `..` segments
- null or control characters
- globs: `*`, `?`, `**`

View File

@ -103,9 +103,11 @@ When strict validation is enabled (`unevaluatedProperties: false`), keep each pr
- Top-level `editor` object.
- Use `editor.componentOverrides` for component overrides.
- Use `editor.layout` for layout.
- **DEPRECATED**: Do NOT use `propertyRenderers` or `view` — these are legacy keys. Always use `componentOverrides` and `layout` instead.
- **Root override pattern** (most common for fully custom editing UI):
- `editor.componentOverrides["$"] = { "definition": "c/<yourEditorComponent>", "attributes": { ... } }`
- When passing schema data into a custom LWC, use attribute mapping with the `{!$attrs.<name>}` syntax: e.g. `"attributes": { "myField": "{!$attrs.value}" }` so the runtime binds schema values to your component's attributes.
- **CRITICAL**: The `<name>` in `{!$attrs.<name>}` must be a property defined in your type schema. For example, if your schema has a property called `temperature`, use `{!$attrs.temperature}`, not `{!$attrs.value}` unless `value` is an actual property.
- **Property-level override pattern** (for individual fields):
- `editor.componentOverrides["<propertyName>"] = { "definition": "es_property_editors/<...>" }`
- **Valid editor components** (examples): `es_property_editors/inputText`, `es_property_editors/inputNumber`, `es_property_editors/inputRichText`, `es_property_editors/inputImage`, `es_property_editors/inputTextarea`. **Do not use** `es_property_editors/inputList`.
@ -113,6 +115,7 @@ When strict validation is enabled (`unevaluatedProperties: false`), keep each pr
- **Layout pattern**:
- `editor.layout.definition = "lightning/verticalLayout"`
- `editor.layout.children[*].definition = "lightning/propertyLayout"` with `attributes.property = "<propertyName>"`
- **CRITICAL**: `lightning/propertyLayout` only accepts the `property` attribute. Do NOT add `label`, `title`, or any other attributes — these will fail validation with `additionalProperties: false` errors.
- **Avoid known-invalid patterns**:
- Do not use `es_property_editors/inputList`.
- Do not use `itemSchema` attributes.
@ -121,18 +124,41 @@ When strict validation is enabled (`unevaluatedProperties: false`), keep each pr
- Top-level `renderer` object.
- Use `renderer.componentOverrides` for component overrides.
- Use `renderer.layout` for layout.
- **DEPRECATED**: Do NOT use `propertyRenderers` or `view` — these are legacy keys. Always use `componentOverrides` and `layout` instead.
- **Root override pattern** (most common for fully custom rendering UI):
- `renderer.componentOverrides["$"] = { "definition": "c/<yourRendererComponent>", "attributes": { ... } }`
- Use `{!$attrs.<name>}` in attribute mappings when binding schema data to custom renderer component attributes.
- **CRITICAL**: Attribute mappings like `{!$attrs.propertyName}` must reference properties that **actually exist** in your type schema. Referencing non-existent properties will fail validation.
- **Type matching**: Attribute values must match the expected type for the component. For example, if a component expects a string attribute, passing an integer will fail validation.
- **Property-level override pattern**:
- `renderer.componentOverrides["<propertyName>"] = { "definition": "es_property_editors/outputText" | "es_property_editors/outputNumber" | "es_property_editors/outputImage" | ... }`. **Valid renderer components** (examples): `es_property_editors/outputText`, `es_property_editors/outputNumber`, `es_property_editors/outputImage`. Avoid input-style components in the renderer.
- **Layout pattern for renderer**:
- `renderer.layout.definition = "lightning/verticalLayout"`
- `renderer.layout.children[*].definition = "lightning/propertyLayout"` with `attributes.property = "<propertyName>"`
- **CRITICAL**: Same as editor layouts, `lightning/propertyLayout` only accepts the `property` attribute. Do NOT add `label`, `title`, or any other attributes.
- **Collection renderer** (for root-level `lightning__listType` properties): Use `collection.renderer.componentOverrides["$"] = { "definition": "c/<yourListRendererComponent>" }` or `es_property_editors/genericListTypeRenderer` to render the list.
5. **Place files in the correct bundle structure**
- `lightningTypes/<TypeName>/schema.json`
- (Optional) `lightningTypes/<TypeName>/lightningDesktopGenAi/editor.json`
- (Optional) `lightningTypes/<TypeName>/lightningDesktopGenAi/renderer.json`
- For Gen AI / Copilot the standard path is `lightningDesktopGenAi/`. Other targets (e.g. Experience Builder, Mobile Copilot, Enhanced Web Chat) use different subfolders when supported: `experienceBuilder/`, `lightningMobileGenAi/`, `enhancedWebChat/`.
6. **Deploy and validate**
6. **Configure custom LWC components (if using custom components)**
- **CRITICAL**: Custom LWC components referenced in editor/renderer configs MUST have the correct target configuration in their `-meta.xml` files:
- **For editor components** (`c/<componentName>` used in `editor.json`): The LWC's `-meta.xml` file must include `<target>lightning__AgentforceInput</target>`
- **For renderer components** (`c/<componentName>` used in `renderer.json`): The LWC's `-meta.xml` file must include `<target>lightning__AgentforceOutput</target>`
- Without the correct target, deployment will fail with: `Invalid target configuration. To use 'c/componentName' as a renderer/editor, your js-meta.xml file must include valid target 'lightning__AgentforceOutput/Input'.`
- Example `-meta.xml` for a renderer component:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>60.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AgentforceOutput</target>
</targets>
</LightningComponentBundle>
```
7. **Deploy and validate**
- Deploy the bundle using your org's standard metadata deployment flow (e.g. Salesforce CLI or IDE). The MCP client or tooling in use should provide or integrate with the appropriate deploy/retrieve commands for Lightning Type bundles.
- Validate incrementally: if deployment fails, remove disallowed keywords first (especially `examples`, `items`, nested `lightning:type`).
@ -144,6 +170,11 @@ When strict validation is enabled (`unevaluatedProperties: false`), keep each pr
| Array property rejected | Use of `items` (or `lightning:type` in nested arrays) rejected by validator | For nested arrays: keep only `type: "array"`. For root arrays: use minimal structure; remove `items` if rejected |
| Apex-based CLT rejected | Extra fields added (e.g., `type`, `properties`) | Use only `title`, optional `description`, and `lightning:type` |
| Editor config rejected | Use of invalid patterns (`es_property_editors/inputList`, `itemSchema`) or unrecognized top-level keys | Use `editor.componentOverrides` and `editor.layout`; keep config minimal |
| `additionalProperties` error on layout attributes | Adding `label` or other attributes to `lightning/propertyLayout` | Only use `property` attribute in `lightning/propertyLayout`. Remove `label`, `title`, or any other attributes |
| Invalid target configuration for custom LWC | Custom LWC component's `-meta.xml` missing required target (`lightning__AgentforceInput` or `lightning__AgentforceOutput`) | Add correct target to LWC's `-meta.xml`: use `lightning__AgentforceInput` for editors, `lightning__AgentforceOutput` for renderers |
| Attribute mapping doesn't exist in type schema | Using `{!$attrs.propertyName}` where `propertyName` is not defined in schema | Ensure all attribute mappings reference actual properties in your type schema's `properties` section |
| `additionalProperties` error with deprecated keys | Using `propertyRenderers` or `view` in editor/renderer config | Replace deprecated `propertyRenderers` with `componentOverrides` and `view` with `layout` |
| Type mismatch in component attributes | Passing wrong type for component attribute (e.g., integer instead of string) | Ensure attribute values match the expected type defined by the component |
## Verification Checklist
- [ ] Root schema has `type: "object"`, `title`, `lightning:type: "lightning__objectType"`, and `unevaluatedProperties: false`
@ -155,3 +186,6 @@ When strict validation is enabled (`unevaluatedProperties: false`), keep each pr
- [ ] Bundle structure and filenames match Lightning Types requirements
- [ ] Editor config uses only allowed patterns (no `es_property_editors/inputList`, no `itemSchema`); use valid components (e.g. `es_property_editors/inputText`, `es_property_editors/inputNumber`) or custom `c/` components
- [ ] Renderer config uses output-style components (e.g. `es_property_editors/outputText`, `es_property_editors/outputNumber`) where applicable, not input editors
- [ ] Layout configurations use `lightning/propertyLayout` with ONLY the `property` attribute (no `label`, `title`, or other attributes)
- [ ] All attribute mappings (`{!$attrs.propertyName}`) reference properties that exist in the type schema
- [ ] Custom LWC components have correct targets in `-meta.xml`: `lightning__AgentforceInput` for editors, `lightning__AgentforceOutput` for renderers

View File

@ -149,6 +149,68 @@ Every fieldInstance requires:
- Must have `fieldInstanceProperties` with `uiBehavior`
- Use `Record.{Field}` format
### 5. Unique Identifiers and Region Names (CRITICAL - PREVENTS DUPLICATE ERRORS)
**EVERY identifier and region/facet name MUST be unique across the entire FlexiPage file.**
**Critical Rules:**
- ❌ **NEVER create two `<flexiPageRegions>` blocks with the same `<name>`**
- ✅ **If multiple components belong to same facet, combine them in ONE region with multiple `<itemInstances>`**
- ❌ **NEVER reuse the same `<identifier>` value**
- ✅ **Always read entire file first and extract ALL existing identifiers and names**
**Wrong - This WILL FAIL with duplicate name error:**
```xml
<!-- 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:**
```xml
<!-- 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:**
- **Combine**: Components that logically belong to same tab/section (e.g., multiple field sections in detail tab)
- **Separate**: Components that belong to different tabs/sections (e.g., `detailTabContent` vs `relatedTabContent`)
---
## Common Deployment Errors
@ -178,7 +240,7 @@ Every fieldInstance requires:
**Fix:** Use "Volunteer_Record_Page" not "Volunteer__c_Record_Page"
### "Region specifies mode that parent doesn't support"
**Cause:** Added `<mode>` tag to region
**Cause:** Added `<mode>` tag to region
**Fix:** Remove `<mode>` tags - they're not needed for standard regions
---
@ -211,21 +273,28 @@ When user provides an existing FlexiPage file path:
1. **Read the file** using native file I/O
2. **Parse XML** to extract:
- Existing component identifiers
- **ALL existing component identifiers** (search for all `<identifier>` tags)
- **ALL existing region/facet names** (search for all `<name>` tags in `<flexiPageRegions>`)
- Available regions (parse from file, don't assume names)
- Existing facets
3. **Generate component XML** (apply all rules from "Critical XML Rules" section)
4. **Insert** into appropriate region
5. **Write** modified XML back to file
6. **Deploy**: `sf project deploy start --source-dir force-app/...`
3. **Verify uniqueness** - ensure your new identifiers and names don't conflict with ANY existing ones
4. **Check if target facet exists** - if adding to a named facet like `detailTabContent` that already exists:
- **Add new `<itemInstances>` to existing region** (don't create duplicate region)
- **Insert before the closing `</flexiPageRegions>` tag of that region**
5. **Generate component XML** (apply all rules from "Critical XML Rules" section)
6. **Insert** into appropriate region or add itemInstances to existing facet
7. **Write** modified XML back to file
8. **Deploy**: `sf project deploy start --source-dir force-app/...`
---
### Generating Unique Identifiers
**Algorithm**:
**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> values from XML
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:
@ -253,6 +322,11 @@ When user provides an existing FlexiPage file path:
- Example: `Facet-66d5a4b3-bf14-4665-ba75-1ceaa71b2cde`
- Use for field section columns, nested containers, anonymous slots
**When adding components to existing files:**
- Check if target facet name already exists
- If exists: Add new `<itemInstances>` to that existing region (see section 5 above for details)
- If doesn't exist: Create new region with unique name
---
### Region Selection
@ -401,6 +475,9 @@ Identifier Pattern: flexipage_richText or flexipage_richText_{sequence}
Before deploying:
- [ ] Used CLI to bootstrap (don't start from scratch)
- [ ] **ALL identifiers are unique** - no duplicate `<identifier>` values anywhere in file
- [ ] **ALL region/facet names are unique** - no duplicate `<name>` values in `<flexiPageRegions>`
- [ ] **Multiple components in same facet are combined** - ONE region with multiple `<itemInstances>`, NOT separate regions with same name
- [ ] All field references use `Record.{Field}` format
- [ ] Each fieldInstance has `fieldInstanceProperties` with `uiBehavior`
- [ ] Each fieldInstance in own `<itemInstances>` wrapper

View File

@ -1,347 +0,0 @@
---
name: generating-lightning-app-solution
description: Build complete Salesforce Lightning Experience applications from natural language descriptions. Use this skill when a user requests a "complete app", "Lightning app", "business solution", "management system", or describes a scenario requiring multiple interconnected Salesforce components (objects, fields, pages, tabs, security). Orchestrates all required metadata types in proper dependency order to produce a deployable application.
metadata:
category: orchestration
version: "1.0"
related-skills: skills/generating-custom-object/SKILL.md, skills/generating-custom-field/SKILL.md, skills/generating-custom-tab/SKILL.md, skills/generating-flexipage/SKILL.md, skills/generating-custom-application/SKILL.md, skills/generating-flow/SKILL.md, skills/generating-validation-rule/SKILL.md, skills/generating-list-view/SKILL.md, skills/generating-permission-set/SKILL.md
---
# Generating Lightning App Solution
## Overview
Build a complete, deployable Salesforce Lightning Experience application from a natural language description by orchestrating multiple metadata types in correct dependency order. Invoke specialized metadata skills when available; generate metadata directly when no skill exists.
## When to Use This Skill
**Use when:**
- User requests a "complete app", "Lightning app", or "end-to-end solution"
- User says "build an app", "create an application", "build a [type] app" (project management, tracking, etc.)
- Request involves 3+ metadata types working together (objects + fields + pages + security)
- User describes multiple custom objects with relationships between them
- User mentions custom objects AND Lightning Record Pages in the same request
- User mentions custom objects AND permission sets/security in the same request
- Request includes phrases like "allows users to manage/track", "management system", "tracking app"
- Need to ensure proper sequencing (Objects → Fields → UI → Security)
**Examples that should trigger this skill:**
- "Build a project management app with Tasks, Resources, and Supplies objects"
- "Create an app to track vehicles with Lightning pages and permission sets"
- "I need a Space Station management system with multiple objects and relationships"
- "Build an employee onboarding app with custom Lightning Record Pages"
**Do NOT use when:**
- Creating a single metadata component (use specific metadata skill instead)
- Troubleshooting or debugging existing metadata
- Building Salesforce Classic apps (not Lightning Experience)
- User asks for just one object, or just one page, or just one permission set (without others)
- User only needs to create or configure an app container (grouping existing tabs) without other metadata — use skills/generating-custom-application/SKILL.md instead
## Metadata Type Registry
This table shows which metadata types are commonly needed for LEX apps and their skill availability.
| Metadata Type | Skill Available? | Skill Name | Usage Rule |
|---------------|------------------|------------|------------|
| **Custom Object** | ✅ YES | `skills/generating-custom-object/SKILL.md` | MUST use skill |
| **Custom Field** | ✅ YES | `skills/generating-custom-field/SKILL.md` | MUST use skill |
| **Custom Tab** | ✅ YES | `skills/generating-custom-tab/SKILL.md` | MUST use skill |
| **FlexiPage** | ✅ YES | `skills/generating-flexipage/SKILL.md` | MUST use skill |
| **Custom Application** | ✅ YES | `skills/generating-custom-application/SKILL.md` | MUST use skill |
| **List View** | ✅ YES | `skills/generating-list-view/SKILL.md` | MUST use skill |
| **Validation Rule** | ✅ YES | `skills/generating-validation-rule/SKILL.md` | MUST use skill (if requested) |
| **Flow** | ✅ YES | `skills/generating-flow/SKILL.md` | MUST use skill (if requested) |
| **Permission Set** | ✅ YES | `skills/generating-permission-set/SKILL.md` | MUST use skill |
### Skill Usage Rules
**CRITICAL RULE**: When a skill exists for a metadata type (✅ YES in table above), you **MUST** invoke that skill. Do NOT generate the metadata directly.
**FALLBACK RULE**: When NO skill exists for a metadata type (❌ NO in table above), you **MAY** generate the metadata directly using your knowledge of Salesforce Metadata API and best practices.
**RATIONALE**: Specialized skills contain validated patterns, error handling, and field-specific knowledge that prevent deployment failures.
---
## Dependency Graph & Build Order
### Phase 1: Data Model (Foundation)
```
Custom Objects (no dependencies)
Custom Fields (depends on: Objects exist)
Relationships (depends on: Both parent and child objects + fields exist)
```
**Skills to invoke in order:**
1. `skills/generating-custom-object/SKILL.md` — once, with all objects
2. `skills/generating-custom-field/SKILL.md` — once, with all fields (including Master-Detail, Lookup, Roll-up Summary)
### Phase 2: Business Logic (Optional - only if requested)
```
Validation Rules (depends on: Fields exist)
Flows (depends on: Objects, Fields exist)
```
**Skills to invoke (only if user requested):**
1. `skills/generating-validation-rule/SKILL.md` — once, if validation requirements mentioned
2. `skills/generating-flow/SKILL.md` — once, if automation/workflow requirements mentioned
### Phase 3: User Interface
```
List Views (depends on: Objects, Fields exist)
Custom Tabs (depends on: Objects exist)
FlexiPages (depends on: Objects, Tabs exist)
```
**Skills to invoke in order:**
1. `skills/generating-list-view/SKILL.md` — once, for filtered record views (if requested)
2. `skills/generating-custom-tab/SKILL.md` — once, with all object tabs
3. `skills/generating-flexipage/SKILL.md` — once, with all record/home/app pages
### Phase 4: Application Assembly
```
Custom Application (depends on: Tabs exist)
```
**Skills to invoke:**
1. `skills/generating-custom-application/SKILL.md` — once, to create the Lightning App container
### Phase 5: Security & Access
```
Permission Sets (depends on: Objects, Fields, Tabs, App exist)
```
**Skills to invoke:**
1. `skills/generating-permission-set/SKILL.md` — once, with all permission sets and access to:
- Objects (Read, Create, Edit, Delete)
- Fields (Read, Edit)
- Tabs (Visible)
- Custom Application (Visible)
---
## Execution Workflow
### STEP 1: Requirements Analysis & Planning
**Actions:**
1. Parse user's natural language request
2. Extract business entities (become Custom Objects)
3. Extract attributes/properties (become Custom Fields)
4. Identify relationships (Master-Detail, Lookup)
5. Detect validation requirements (become Validation Rules)
6. Detect automation requirements (become Flows)
7. Identify user personas (inform Permission Sets)
**Output: Build Plan**
Generate a structured plan listing:
```
📋 Lightning App Build Plan: [App Name]
DATA MODEL:
- Custom Objects: [list with object names]
- Custom Fields: [list grouped by object]
- Relationships: [list M-D and Lookup relationships]
BUSINESS LOGIC (if applicable):
- Validation Rules: [list with object and rule name]
- Flows: [list with flow name and type]
USER INTERFACE:
- List Views: [list with object and view name]
- Custom Tabs: [list with object]
- FlexiPages: [list with page name and type]
- Custom Application: [app name]
SECURITY:
- Permission Sets: [list with purpose]
METADATA SKILLS TO INVOKE:
- skills/generating-custom-object/SKILL.md (x 1)
- skills/generating-custom-field/SKILL.md (x 1)
- skills/generating-validation-rule/SKILL.md (x 1) - if validation requirements identified
- skills/generating-flow/SKILL.md (x 1) - if automation requirements identified
- skills/generating-custom-tab/SKILL.md (x 1)
- skills/generating-flexipage/SKILL.md (x 1)
- skills/generating-custom-application/SKILL.md (x 1)
- skills/generating-permission-set/SKILL.md (x 1)
DEPENDENCY ORDER:
1. Phase 1: Data Model (Objects → Fields)
2. Phase 2: Business Logic (Validation Rules → Flows)
3. Phase 3: User Interface (List Views → Tabs → Pages)
4. Phase 4: App Assembly (Application)
5. Phase 5: Security (Permission Sets)
```
### STEP 2: Skill Invocation Sequence
Execute in strict dependency order. Invoke each skill once with all components for that metadata type.
1. **Check Metadata Type Registry**: Does a skill exist?
2. **If YES (✅)**: Invoke the specialized skill once with all components for that type
3. **If NO (❌)**: Generate metadata directly using Metadata API knowledge
4. **Handle Errors**: If skill invocation fails, log error and continue (don't block entire app)
**Invocation Pattern (one invocation per metadata type):**
- Custom Objects → Invoke `skills/generating-custom-object/SKILL.md` once with all objects
- Custom Fields → Invoke `skills/generating-custom-field/SKILL.md` once with all fields
- Validation Rules → Invoke `skills/generating-validation-rule/SKILL.md` once (if requested)
- Flows → Invoke `skills/generating-flow/SKILL.md` once (if requested)
- Custom Tabs → Invoke `skills/generating-custom-tab/SKILL.md` once with all tabs
- FlexiPages → Invoke `skills/generating-flexipage/SKILL.md` once with all pages
- Custom Application → Invoke `skills/generating-custom-application/SKILL.md` once
- Permission Sets → Invoke `skills/generating-permission-set/SKILL.md` once with all permission sets
### STEP 3: Final Artifact Assembly
After all phases complete, consolidate outputs into deployment-ready structure.
---
## Output
The completed build produces:
1. **Salesforce DX Project Directory** containing all generated metadata
- Organized by standard SFDX structure: `force-app/main/default/`
2. **Metadata Files** - One file per component, organized by type:
```
force-app/main/default/
├── objects/ # Custom Objects (.object-meta.xml)
├── fields/ # Custom Fields (.field-meta.xml)
├── tabs/ # Custom Tabs (.tab-meta.xml)
├── flexipages/ # Lightning Pages (.flexipage-meta.xml)
├── applications/ # Custom Applications (.app-meta.xml)
├── permissionsets/ # Permission Sets (.permissionset-meta.xml)
├── flows/ # Flows (.flow-meta.xml) - if applicable
└── objects/.../validationRules/ # Validation Rules (.validationRule-meta.xml) - if applicable
```
3. **Deployment Manifest** (`package.xml`)
- Lists all components with proper API version
- Organized by metadata type in dependency order
- Ready for Salesforce CLI deployment or Metadata API deployment
4. **Build Summary Report** - A markdown file listing:
- Every component created
- Component type and API name
- File path location
- Dependency relationships
- Any warnings or recommendations
**Example Summary Structure:**
```
📦 Lightning App Build Complete: Project Management App
METADATA GENERATED:
✅ 3 Custom Objects
- Project__c → force-app/main/default/objects/Project__c/Project__c.object-meta.xml
- Task__c → force-app/main/default/objects/Task__c/Task__c.object-meta.xml
- Resource__c → force-app/main/default/objects/Resource__c/Resource__c.object-meta.xml
✅ 12 Custom Fields
- Project__c.Name → force-app/main/default/objects/Project__c/fields/Name.field-meta.xml
- Project__c.Status__c → force-app/main/default/objects/Project__c/fields/Status__c.field-meta.xml
[... etc ...]
✅ 3 Custom Tabs
- Project__c → force-app/main/default/tabs/Project__c.tab-meta.xml
[... etc ...]
✅ 3 Lightning Record Pages
- Project_Record_Page → force-app/main/default/flexipages/Project_Record_Page.flexipage-meta.xml
[... etc ...]
✅ 1 Custom Application
- Project_Management → force-app/main/default/applications/Project_Management.app-meta.xml
✅ 2 Permission Sets
- Project_Manager → force-app/main/default/permissionsets/Project_Manager.permissionset-meta.xml
- Project_User → force-app/main/default/permissionsets/Project_User.permissionset-meta.xml
⚠️ WARNINGS: None
```
---
## Validation
Before presenting the completed build to the user, verify cross-component integrity:
- [ ] **Object-Tab Coverage**: Every Custom Object has at least one Custom Tab
- [ ] **Relationship Integrity**: Every Custom Object referenced in a relationship (parent or child) exists in the build
- [ ] **Field References in Pages**: Every field referenced in a FlexiPage exists on the corresponding object
- [ ] **Tab References in App**: Every tab referenced in the Custom Application was successfully created
- [ ] **Permission Set Completeness**: Permission Sets grant access to all generated objects, fields, tabs, and the application
- [ ] **No Orphaned Components**: No tabs without objects, no pages without corresponding tabs, no app without tabs
- [ ] **Deployment Manifest Completeness**: `package.xml` includes all generated components in proper dependency order
**Validation Failure Handling:**
- If validation fails, include failed checks in the Build Summary Report under a `⚠️ VALIDATION WARNINGS` section
- Do NOT block delivery of the build, but clearly communicate what needs manual review or correction
- Provide specific remediation steps for each failed validation check
**Note**: Individual component validations (reserved words, name lengths, field types, etc.) are handled by specialized metadata skills and do not need to be re-validated here.
---
## Error Handling
### Critical Errors (Stop Execution)
Stop and ask user for clarification if:
- User request is too vague to extract any objects or fields
- Conflicting requirements detected (e.g., "make it private" + "everyone should see it")
- Invalid Salesforce naming detected (reserved words like `Order`, `Group`)
### Non-Critical Errors (Continue with Warning)
Log warning and continue if:
- Optional component fails (e.g., List View generation fails)
- Skill invocation fails for non-critical metadata
- Validation Rule or Flow has minor issues
**Warning Pattern:**
```
⚠️ Warning: [Component Type] generation encountered issue
Component: [Name]
Issue: [Description]
Impact: [What won't work]
Recommendation: [How to fix manually]
Continuing with remaining components...
```
---
## Best Practices
### 1. Always Follow Dependency Order
Never invoke skills out of sequence. Fields need objects, pages need tabs, apps need tabs.
### 2. Use Skills When Available
Don't reinvent the wheel. Specialized skills have field-specific validation that prevents deployment errors.
### 3. Generate Thoughtful Defaults
When user doesn't specify details:
- Use Text name fields for human entities
- Use AutoNumber for transactions
- Enable Search and Reports for user-facing objects
- Set sharingModel based on relationships
### 4. Validate Before Building
Check for:
- Reserved words in API names
- Relationship limits (max 2 M-D per object)
- Name length limits
- Duplicate names

View File

@ -0,0 +1,423 @@
---
name: generating-lightning-app
description: Build complete Salesforce Lightning Experience applications from natural language descriptions. Use this skill when a user requests a "complete app", "Lightning app", "business solution", "management system", or describes a scenario requiring multiple interconnected Salesforce components (objects, fields, pages, tabs, security). Orchestrates all required metadata types in proper dependency order to produce a deployable application.
metadata:
version: "1.0"
related-skills: generating-custom-object, generating-custom-field, generating-custom-tab, generating-flexipage, generating-custom-application, generating-flow, generating-validation-rule, generating-list-view, generating-permission-set
---
# Generating Lightning App
## Overview
Build a complete, deployable Salesforce Lightning Experience application from a natural language description by defining a Lightning Custom Application and orchestrating its dependent metadata types in correct dependency order. Invoke specialized metadata skills when available; generate metadata directly when no skill exists.
## When to Use This Skill
**Use when:**
- User requests a "Lightning app", or "end-to-end solution"
- User says "build an app", "create an application", "build a [type] app" (project management, tracking, etc.)
- The work produces a custom app (CustomApplication) plus supporting metadata, not a lone object, page, or tab in isolation
**Examples that should trigger this skill:**
- "Build a project management lightning app with Tasks, Resources, and Supplies objects"
- "Create a LEX app to track vehicles with Lightning pages and permission sets"
- "I need a Space Station management system with multiple objects and relationships"
- "Build an employee onboarding lightning app with custom Lightning Record Pages"
**Do NOT use when:**
- Creating a single metadata component (use specific metadata skill instead)
- Troubleshooting or debugging existing metadata
- Building Salesforce Classic apps (not Lightning Experience)
- User asks for just one object, or just one page, or just one permission set (without others)
- User only needs to create or configure an app container (grouping existing tabs) without other metadata; use `generating-custom-application` instead
## Metadata Type Registry
This table shows which metadata types are commonly needed for Lightning Experience apps, their skill availability, and API context requirement.
| Metadata Type | Skill Name | API Context | Usage Rule |
|---------------|------------|-------------|------------|
| **Custom Object** | `generating-custom-object` | `salesforce-api-context` | MUST load skill AND call API context |
| **Custom Field** | `generating-custom-field` | `salesforce-api-context` | MUST load skill AND call API context |
| **Custom Tab** | `generating-custom-tab` | `salesforce-api-context` | MUST load skill AND call API context |
| **FlexiPage** | `generating-flexipage` | `salesforce-api-context` | MUST load skill AND call API context |
| **Custom Application** | `generating-custom-application` | `salesforce-api-context` | MUST load skill AND call API context |
| **List View** | `generating-list-view` | `salesforce-api-context` | MUST load skill AND call API context (if requested) |
| **Validation Rule** | `generating-validation-rule` | `salesforce-api-context` | MUST load skill AND call API context (if requested) |
| **Flow** | `generating-flow` | `metadata-experts` pipeline | MUST load skill AND run pipeline. **Exempt from `salesforce-api-context`**. |
| **Permission Set** | `generating-permission-set` | `salesforce-api-context` | MUST load skill AND call API context |
### Usage Rules
**SKILL RULE**: When a skill exists for a metadata type, you **MUST** load that skill. Do NOT generate metadata directly without loading the skill first.
**API CONTEXT RULE**: For every metadata type (except Flow), you **MUST** call `salesforce-api-context` tools before generating. Do NOT generate metadata without calling API context first. The skill provides structure and rules; API context confirms what is valid for the current API version. Both are essential.
**FALLBACK RULE**: When no skill exists for a metadata type you need, generate the metadata directly using your knowledge of Salesforce Metadata API and best practices. API context is still required.
**RATIONALE**: Skills contain validated patterns and constraints. API context provides version-specific accuracy. Together they prevent deployment failures.
---
## Dependency Graph & Build Order
### Phase 1: Data Model (Foundation)
```
Custom Objects (no dependencies)
Custom Fields (depends on: Objects exist)
Relationships (depends on: Both parent and child objects + fields exist)
```
**Metadata types in this phase:**
1. `generating-custom-object` - once, with all objects
2. `generating-custom-field` - once, with all fields (including Master-Detail, Lookup, Roll-up Summary)
### Phase 2: Business Logic (Optional - only if requested)
```
Validation Rules (depends on: Fields exist)
Flows (depends on: Objects, Fields exist)
```
**Metadata types in this phase (only if user requested):**
1. `generating-validation-rule` - once, if validation requirements mentioned
2. `generating-flow` - once, if automation/workflow requirements mentioned
### Phase 3: User Interface
```
List Views (depends on: Objects, Fields exist)
Custom Tabs (depends on: Objects exist)
FlexiPages (depends on: Objects, Tabs exist)
```
**Metadata types in this phase:**
1. `generating-list-view` - once, for filtered record views (if requested)
2. `generating-custom-tab` - once, with all object tabs
3. `generating-flexipage` - once, with all record/home/app pages
### Phase 4: Application Assembly
```
Custom Application (depends on: Tabs exist)
```
**Metadata types in this phase:**
1. `generating-custom-application` - once, to create the Lightning App container
### Phase 5: Security & Access
```
Permission Sets (depends on: Objects, Fields, Tabs, App exist)
```
**Metadata types in this phase:**
1. `generating-permission-set` - once, with all permission sets and access to:
- Objects (Read, Create, Edit, Delete)
- Fields (Read, Edit)
- Tabs (Visible)
- Custom Application (Visible)
---
## Execution Workflow
### STEP 1: Requirements Analysis & Planning
**Actions:**
1. Parse user's natural language request
2. Extract business entities (become Custom Objects)
3. Extract attributes/properties (become Custom Fields)
4. Identify relationships (Master-Detail, Lookup)
5. Detect validation requirements (become Validation Rules)
6. Detect automation requirements (become Flows)
7. Identify user personas (inform Permission Sets)
**Output: Build Plan**
Generate a structured plan listing:
```
Lightning App Build Plan: [App Name]
DATA MODEL:
- Custom Objects: [list with object names]
- Custom Fields: [list grouped by object]
- Relationships: [list M-D and Lookup relationships]
BUSINESS LOGIC (if applicable):
- Validation Rules: [list with object and rule name]
- Flows: [list with flow name and type]
USER INTERFACE:
- List Views (if requested): [list with object and view name]
- Custom Tabs: [list with object]
- FlexiPages: [list with page name and type]
- Custom Application: [app name]
SECURITY:
- Permission Sets: [list with purpose]
PER-TYPE EXECUTION (skill + API context for each):
- CustomObject: load generating-custom-object + call salesforce-api-context
- CustomField: load generating-custom-field + call salesforce-api-context
- ValidationRule: load generating-validation-rule + call salesforce-api-context (if requested)
- Flow: load generating-flow + run metadata-experts pipeline (if requested)
- ListView: load generating-list-view + call salesforce-api-context (if requested)
- CustomTab: load generating-custom-tab + call salesforce-api-context
- FlexiPage: load generating-flexipage + call salesforce-api-context
- CustomApplication: load generating-custom-application + call salesforce-api-context
- PermissionSet: load generating-permission-set + call salesforce-api-context
STATUS LINES TO EMIT BEFORE FILE WRITES:
- `type=<Type> skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- Flow exception: `type=Flow skill=complete pipeline=complete`
DEPENDENCY ORDER:
1. Phase 1: Data Model (Objects -> Fields)
2. Phase 2: Business Logic (Validation Rules -> Flows)
3. Phase 3: User Interface (List Views -> Tabs -> Pages)
4. Phase 4: App Assembly (Application)
5. Phase 5: Security (Permission Sets)
```
### STEP 2: Per-Type Execution
Execute these four steps for each metadata type, one type at a time. Complete all four steps for the current type before moving to the next type. Do NOT skip any step.
| Step | What to do | Why |
|------|-----------|-----|
| **① Load skill** | Search for and read the per-type SKILL.md | Gives you the XML structure, required elements, naming rules, and validation constraints |
| **② Call API context** | Call `salesforce-api-context` tools for this metadata type using one or more of: `get_metadata_type_sections`, `get_metadata_type_context`, `get_metadata_type_fields`, `get_metadata_type_fields_properties`, `search_metadata_types` | Gives you the current valid values — allowed enum values, required vs. optional fields, child types for this API version. The skill provides structure; API context provides version-specific accuracy. |
| **③ Record status** | Emit: `type=<Type> skill=complete mcp=complete\|unavailable mcp_tools=<tool-list\|none>` | Confirms both steps were attempted before any files are written and records which API context tools were used |
| **④ Generate files** | Generate all files for this type, then checkpoint | Only after ①②③ are done. Verify, then move to the next type. |
**Do NOT combine ① and ② into a single action or skip ② after completing ①.** They are separate steps that serve different purposes. After loading the skill you may feel ready to generate — stop and do ② first.
If `salesforce-api-context` is unavailable after a real attempt, record `mcp=unavailable` and generate using skill knowledge alone. Not attempting ② at all is a bug.
---
**1. Custom Objects**
- ① Load skill: Read `generating-custom-object` SKILL.md
- ② API context: Call `salesforce-api-context` for CustomObject
- ③ Status: `type=CustomObject skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all Custom Object files, then proceed to #2
**2. Custom Fields**
- ① Load skill: Read `generating-custom-field` SKILL.md
- ② API context: Call `salesforce-api-context` for CustomField
- ③ Status: `type=CustomField skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all Custom Field files, then proceed to #3
**3. Validation Rules** (only if requested)
- ① Load skill: Read `generating-validation-rule` SKILL.md
- ② API context: Call `salesforce-api-context` for ValidationRule
- ③ Status: `type=ValidationRule skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all Validation Rule files, then proceed to #4
**4. Flows** (only if requested)
- ① Load skill: Read `generating-flow` SKILL.md
- ② Pipeline: Run `metadata-experts/execute_metadata_action` 3-step pipeline (exempt from `salesforce-api-context`)
- ③ Status: `type=Flow skill=complete pipeline=complete`
- ④ Generate + Checkpoint: Generate all Flow files via the pipeline, then proceed to #5
**5. List Views** (only if requested)
- ① Load skill: Read `generating-list-view` SKILL.md
- ② API context: Call `salesforce-api-context` for ListView
- ③ Status: `type=ListView skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all List View files, then proceed to #6
**6. Custom Tabs**
- ① Load skill: Read `generating-custom-tab` SKILL.md
- ② API context: Call `salesforce-api-context` for CustomTab
- ③ Status: `type=CustomTab skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all Custom Tab files, then proceed to #7
**7. FlexiPages**
- ① Load skill: Read `generating-flexipage` SKILL.md
- ② API context: Call `salesforce-api-context` for FlexiPage
- ③ Status: `type=FlexiPage skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all FlexiPage files, then proceed to #8
**8. Custom Application**
- ① Load skill: Read `generating-custom-application` SKILL.md
- ② API context: Call `salesforce-api-context` for CustomApplication
- ③ Status: `type=CustomApplication skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate the Custom Application file, then proceed to #9
**9. Permission Sets**
- ① Load skill: Read `generating-permission-set` SKILL.md
- ② API context: Call `salesforce-api-context` for PermissionSet
- ③ Status: `type=PermissionSet skill=complete mcp=complete|unavailable mcp_tools=<tool-list|none>`
- ④ Generate + Checkpoint: Generate all Permission Set files — all types complete
### STEP 3: Final Artifact Assembly
After all phases complete, consolidate outputs into deployment-ready structure.
---
## Output
The completed build produces:
1. **Salesforce DX Project Directory** containing all generated metadata
- Organized by standard SFDX structure: `force-app/main/default/`
2. **Metadata Files** - One file per component, organized by type:
```
force-app/main/default/
├── objects/ # Custom Objects (.object-meta.xml)
├── fields/ # Custom Fields (.field-meta.xml)
├── tabs/ # Custom Tabs (.tab-meta.xml)
├── flexipages/ # Lightning Pages (.flexipage-meta.xml)
├── applications/ # Custom Applications (.app-meta.xml)
├── permissionsets/ # Permission Sets (.permissionset-meta.xml)
├── flows/ # Flows (.flow-meta.xml) - if applicable
└── objects/.../validationRules/ # Validation Rules (.validationRule-meta.xml) - if applicable
```
3. **Deployment Manifest** (`package.xml`)
- Lists all components with proper API version
- Organized by metadata type in dependency order
- Ready for Salesforce CLI deployment or Metadata API deployment
4. **Build Summary Report** - A markdown file listing:
- Every component created
- Component type and API name
- File path location
- Dependency relationships
- Any warnings or recommendations
**Example Summary Structure:**
```
Lightning App Build Complete: Project Management App
METADATA GENERATED:
1 Custom Objects
- Project__c -> force-app/main/default/objects/Project__c/Project__c.object-meta.xml
- Task__c -> force-app/main/default/objects/Task__c/Task__c.object-meta.xml
- Resource__c -> force-app/main/default/objects/Resource__c/Resource__c.object-meta.xml
2 Custom Fields
- Project__c.Name -> force-app/main/default/objects/Project__c/fields/Name.field-meta.xml
- Project__c.Status__c -> force-app/main/default/objects/Project__c/fields/Status__c.field-meta.xml
[... etc ...]
3 Custom Tabs
- Project__c -> force-app/main/default/tabs/Project__c.tab-meta.xml
[... etc ...]
4 Lightning Record Pages
- Project_Record_Page -> force-app/main/default/flexipages/Project_Record_Page.flexipage-meta.xml
[... etc ...]
5 Custom Application
- Project_Management -> force-app/main/default/applications/Project_Management.app-meta.xml
6 Permission Sets
- Project_Manager -> force-app/main/default/permissionsets/Project_Manager.permissionset-meta.xml
- Project_User -> force-app/main/default/permissionsets/Project_User.permissionset-meta.xml
WARNINGS: None
```
---
## Validation
Before presenting the completed build to the user, verify cross-component integrity:
- [ ] **Object-Tab Coverage**: Every Custom Object has at least one Custom Tab
- [ ] **Relationship Integrity**: Every Custom Object referenced in a relationship (parent or child) exists in the build
- [ ] **Field References in Pages**: Every field referenced in a FlexiPage exists on the corresponding object
- [ ] **Tab References in App**: Every tab referenced in the Custom Application was successfully created
- [ ] **Permission Set Completeness**: Permission Sets grant access to all generated objects, fields, tabs, and the application
- [ ] **No Orphaned Components**: No tabs without objects, no pages without corresponding tabs, no app without tabs
- [ ] **Deployment Manifest Completeness**: `package.xml` includes all generated components in proper dependency order
**Validation Failure Handling (Category 2):**
- If validation fails, include failed checks in the Build Summary Report under a `VALIDATION WARNINGS` section
- These are post-generation issues — do NOT block delivery of the build, but clearly communicate what needs manual review or correction
- Provide specific remediation steps for each failed validation check
**Note**: Individual component validations (reserved words, name lengths, field types, etc.) are handled by specialized metadata skills and do not need to be re-validated here.
---
## Error Handling
### Category 1: Stop and Ask User
Stop execution and ask for clarification if:
- User request is too vague to extract any objects or fields
- Conflicting requirements detected (e.g., "make it private" + "everyone should see it")
- Invalid Salesforce naming detected (reserved words like `Order`, `Group`)
### Category 2: Post-Generation Warnings (Log Warning, Continue)
Log warning and continue if:
- Cross-component validation check fails (e.g., field referenced in FlexiPage doesn't exist on object)
- Optional component generation fails (e.g., List View generation has minor issues)
- Validation Rule or Flow has minor output issues
**Warning Pattern:**
```
Warning: [Component Type] generation encountered issue
Component: [Name]
Issue: [Description]
Impact: [What won't work]
Recommendation: [How to fix manually]
Continuing with remaining components...
```
---
## Best Practices
### 1. Always Follow Dependency Order
Never invoke skills out of sequence. Fields need objects, pages need tabs, apps need tabs.
### 2. Use Skills When Available
Don't reinvent the wheel. Specialized skills have field-specific validation that prevents deployment errors.
### 3. Generate Thoughtful Defaults
When user doesn't specify details:
- Use Text name fields for human entities
- Use AutoNumber for transactions
- Enable Search and Reports for user-facing objects
- Set sharingModel based on relationships
### 4. Validate Before Building
Check for:
- Reserved words in API names
- Relationship limits (max 2 M-D per object)
- Name length limits
- Duplicate names

View File

@ -0,0 +1,28 @@
---
name: switching-org
description: Switches the active Salesforce org (default target-org) using the Salesforce CLI. Use whenever someone wants to change which org CLI commands run against — whether they say "switch org", "change default org", "set my org to", "use alias", "point to", or describe wanting to work against a specific org, scratch org, sandbox, or production.
compatibility: Salesforce CLI (sf) v2+
metadata:
version: "1.0"
---
## Steps
1. Identify the org: the user provides a username or alias (`orgIdentifier`). If not provided, run `sf org list` to show authenticated orgs and ask the user which one to use.
2. Set the default org:
- Local (default): `sf config set target-org <orgIdentifier>`
- Applies only within the current project directory. Use this for normal project work.
- Global (only if user explicitly requests): `sf config set target-org <orgIdentifier> --global`
- Applies system-wide across all directories. Use when working outside a project or when the user asks for global scope.
- If this fails, report the error and suggest running `sf org login web` if the org may not be authorized.
3. Verify:
- `sf config get target-org --json`
- Note: the JSON output does not include a scope/location field — it cannot confirm whether the value is local or global. Confirm the value only, e.g.: `target-org is now set to: <value>`
- If it fails, report the error and advise running `sf config get target-org`.
## Notes
- Unified CLI uses keys like `target-org` and `target-dev-hub`. Legacy sfdx keys (`defaultusername`, `defaultdevhubusername`) are deprecated in this context.
- The sf CLI does not have `--local` or `--scope` flags for config set. Local scope is the default behavior.
- If the org does not change after setting the config, check whether `SF_TARGET_ORG` is set — environment variables override config values.
- Salesforce CLI config (unified) reference: https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_config_commands_unified.htm#cli_reference_config_set_unified