mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-07 08:04:28 +08:00
Merge branch 'main' into main
This commit is contained in:
commit
9bb0d37467
23
.github/workflows/release-skills.yml
vendored
23
.github/workflows/release-skills.yml
vendored
@ -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
|
||||
|
||||
15
CHANGELOG.md
15
CHANGELOG.md
@ -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)
|
||||
|
||||
|
||||
|
||||
@ -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": [
|
||||
|
||||
@ -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 |
|
||||
|
||||
@ -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"
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
"title": "Build Metadata",
|
||||
"contentBody": {
|
||||
"BiometricOptIn": false,
|
||||
"NotificationOptIn": false
|
||||
}
|
||||
"NotificationOptIn": true
|
||||
},
|
||||
"urlName": "build-metadata"
|
||||
}
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"apiName": "rentalApp",
|
||||
"type": "experience__camaECDefinition",
|
||||
"path": "rentalApp"
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"type": "experience__camaECDefinition",
|
||||
"title": "CAMA EC Definition",
|
||||
"contentBody": {}
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"apiName": "calendar",
|
||||
"type": "experience__camaScreen",
|
||||
"path": "calendar"
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"apiName": "home",
|
||||
"type": "experience__camaScreen",
|
||||
"path": "home"
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"apiName": "homeScreen",
|
||||
"type": "experience__camaScreen",
|
||||
"path": "homeScreen"
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"apiName": "propertiesScreen",
|
||||
"type": "experience__camaScreen",
|
||||
"path": "propertiesScreen"
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"apiName": "tenantsScreen",
|
||||
"type": "experience__camaScreen",
|
||||
"path": "tenantsScreen"
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"apiName" : "languages",
|
||||
"type" : "sfdc_cms__languageSettings",
|
||||
"path" : "_settings"
|
||||
}
|
||||
@ -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"
|
||||
}
|
||||
@ -53,7 +53,7 @@ Applies to:
|
||||
|
||||
Reject:
|
||||
- backslashes
|
||||
- leading `/` or `\`
|
||||
- leading `\`
|
||||
- `..` segments
|
||||
- null or control characters
|
||||
- globs: `*`, `?`, `**`
|
||||
|
||||
@ -53,7 +53,7 @@ Applies to:
|
||||
|
||||
Reject:
|
||||
- backslashes
|
||||
- leading `/` or `\`
|
||||
- leading `\`
|
||||
- `..` segments
|
||||
- null or control characters
|
||||
- globs: `*`, `?`, `**`
|
||||
|
||||
@ -53,7 +53,7 @@ Applies to:
|
||||
|
||||
Reject:
|
||||
- backslashes
|
||||
- leading `/` or `\`
|
||||
- leading `\`
|
||||
- `..` segments
|
||||
- null or control characters
|
||||
- globs: `*`, `?`, `**`
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
423
skills/generating-lightning-app/SKILL.md
Normal file
423
skills/generating-lightning-app/SKILL.md
Normal 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
|
||||
28
skills/switching-org/SKILL.md
Normal file
28
skills/switching-org/SKILL.md
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user