-
Notifications
You must be signed in to change notification settings - Fork 101
@W-21582128@: Introduce Skill to Construct a Salesforce Experience React Site #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dbb0351
9dbf15a
3227c9a
2d77109
4ff2be0
6a3640d
f6978be
af775d7
423032d
300e5dd
4ed0e96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| --- | ||
| name: salesforce-experience-react-site | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @hsinghbisht-sfdc The Expert for this Skill was already present in 260/patch (not main), so it wasn't copied over. Adding it now as part of this PR. |
||
| description: Use this skill when users need to create or configure a Salesforce Digital Experience Site specifically for hosting a React web application. Trigger when users mention creating an Experience site for a React app, setting up a React site on Salesforce, configuring Network/CustomSite/DigitalExperience metadata for a web app, or deploying site infrastructure for a React application. Also trigger when users mention site URL path prefixes, app namespaces, appDevName, guest access configuration, DigitalExperienceConfig, DigitalExperienceBundle, or sfdc_cms__site content types in the context of React apps. Always use this skill for any React web application site creation or site infrastructure configuration work, even if the user just says "create a site for my React app" or "set up the site for my web application." | ||
| --- | ||
|
|
||
| # Digital Experience Site for React Web Applications | ||
| Create and configure Digital Experience Sites that host React web applications on Salesforce. This skill generates the minimum necessary site infrastructure — Network, CustomSite, DigitalExperienceConfig, DigitalExperienceBundle, and the `sfdc_cms__site` content type — so a React app can be served from Salesforce. | ||
|
|
||
| React sites differ from standard LWR sites: they don't need routes, views, theme layouts, or branding sets. The site acts as a thin container (`appContainer: true`) that delegates rendering to the React application referenced by `appSpace`. | ||
|
|
||
| ## Required Properties | ||
| Resolve all five properties before generating any metadata. Each has a fallback chain — work through each option in order until a value is found. | ||
|
|
||
| | Property | Format | How to Resolve | | ||
| |----------|--------|----------------| | ||
| | **siteName** | `UpperCamelCase` (e.g., `MyCommunity`) | Ask user or derive from context | | ||
| | **siteUrlPathPrefix** | `kebab-case` (e.g., `my-community`) | User-provided, or convert siteName to kebab-case | | ||
| | **appNamespace** | String | `namespace` in `sfdx-project.json` → `sf data query -q "SELECT NamespacePrefix FROM Organization" --target-org ${usernameOrAlias}` → default `c` | | ||
| | **appDevName** | String | `webApplication` metadata in the project → `sf data query -q "SELECT DeveloperName FROM WebApplication" --target-org ${usernameOrAlias}` → default to siteName | | ||
| | **enableGuestAccess** | Boolean | Ask user whether unauthenticated guest users can access site APIs → default `false` | | ||
|
|
||
| The `appNamespace` and `appDevName` properties connect the site to the correct React application. Getting these wrong means the site deploys but shows a blank page, so take care to resolve them from real project data. | ||
|
|
||
| ## Generation Workflow | ||
| ### Step 1: Resolve All Required Properties | ||
| Determine values for all five properties before constructing anything. Use the resolution strategies in the table above, falling through each option until a value is found. | ||
|
|
||
| ### Step 2: Create the Project Structure | ||
| Call the `get_metadata_api_context` MCP tool to retrieve schemas for `Network`, `CustomSite`, `DigitalExperienceConfig`, and `DigitalExperienceBundle` metadata types. These schemas define the valid XML structure for each file. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to:
|
||
|
|
||
| Create any files and directories that don't already exist, using these paths: | ||
|
|
||
| | Metadata Type | Path | | ||
| |--------------|------| | ||
| | Network | `networks/{siteName}.network-meta.xml` | | ||
| | CustomSite | `sites/{siteName}.site-meta.xml` | | ||
| | DigitalExperienceConfig | `digitalExperienceConfigs/{siteName}1.digitalExperienceConfig-meta.xml` | | ||
| | DigitalExperienceBundle | `digitalExperiences/site/{siteName}1/{siteName}1.digitalExperience-meta.xml` | | ||
| | DigitalExperience (sfdc_cms__site) | `digitalExperiences/site/{siteName}1/sfdc_cms__site/{siteName}1/*` | | ||
|
|
||
| The DigitalExperience directory contains only `_meta.json` and `content.json`. Do not create any directories other than `sfdc_cms__site` inside the bundle. | ||
|
|
||
| ### Step 3: Populate All Metadata Fields | ||
| Use the default templates in the docs below. Values in `{braces}` are resolved property references — substitute them with the actual values from Step 1. | ||
|
|
||
| | Metadata Type | Template Reference | | ||
| |--------------|-------------------| | ||
| | Network | [configure-metadata-network.md](docs/configure-metadata-network.md) | | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We delegate each metadata file template to a doc as reference. In the future, these could be made a part of an |
||
| | CustomSite | [configure-metadata-custom-site.md](docs/configure-metadata-custom-site.md) | | ||
| | DigitalExperienceConfig | [configure-metadata-digital-experience-config.md](docs/configure-metadata-digital-experience-config.md) | | ||
| | DigitalExperienceBundle | [configure-metadata-digital-experience-bundle.md](docs/configure-metadata-digital-experience-bundle.md) | | ||
| | DigitalExperience (sfdc_cms__site) | [configure-metadata-digital-experience.md](docs/configure-metadata-digital-experience.md) | | ||
|
|
||
| ### Step 4: Resolve Additional Configurations | ||
| Address any extra configurations the user requests. Use the schemas returned by `get_metadata_api_context` in Step 2 to understand each field's purpose, and update only the minimum necessary fields. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to use either |
||
|
|
||
| ## Verification Checklist | ||
| Before deploying, confirm: | ||
|
|
||
| - [ ] All five required properties are resolved | ||
| - [ ] All metadata directories and files exist per the project structure | ||
| - [ ] All metadata fields are populated per the templates and user requests | ||
| - [ ] `appSpace` in `content.json` matches an existing `WebApplication` metadata record | ||
| - [ ] Deployment validates successfully: | ||
| ```bash | ||
| sf project deploy validate --metadata Network CustomSite DigitalExperienceConfig DigitalExperienceBundle DigitalExperience --target-org ${usernameOrAlias} | ||
| ``` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # Configure Metadata: CustomSite | ||
|
|
||
| ## Purpose | ||
| This configuration file creates a **net-new, default** CustomSite metadata record for a Digital Experience React Site. It is not intended to edit or modify an existing CustomSite record. Use this template only when provisioning a brand-new React site. | ||
|
|
||
| ## File Location | ||
| ``` | ||
| sites/{siteName}.site-meta.xml | ||
| ``` | ||
|
|
||
| ## Default Template | ||
| ```xml | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <CustomSite xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
| <active>true</active> | ||
| <allowGuestPaymentsApi>false</allowGuestPaymentsApi> | ||
| <allowHomePage>false</allowHomePage> | ||
| <allowStandardAnswersPages>false</allowStandardAnswersPages> | ||
| <allowStandardIdeasPages>false</allowStandardIdeasPages> | ||
| <allowStandardLookups>false</allowStandardLookups> | ||
| <allowStandardPortalPages>true</allowStandardPortalPages> | ||
| <allowStandardSearch>false</allowStandardSearch> | ||
| <authorizationRequiredPage>CommunitiesLogin</authorizationRequiredPage> | ||
| <bandwidthExceededPage>BandwidthExceeded</bandwidthExceededPage> | ||
| <browserXssProtection>true</browserXssProtection> | ||
| <cachePublicVisualforcePagesInProxyServers>true</cachePublicVisualforcePagesInProxyServers> | ||
| <clickjackProtectionLevel>SameOriginOnly</clickjackProtectionLevel> | ||
| <contentSniffingProtection>true</contentSniffingProtection> | ||
| <enableAuraRequests>true</enableAuraRequests> | ||
| <fileNotFoundPage>FileNotFound</fileNotFoundPage> | ||
| <genericErrorPage>Exception</genericErrorPage> | ||
| <inMaintenancePage>InMaintenance</inMaintenancePage> | ||
| <indexPage>CommunitiesLanding</indexPage> | ||
| <masterLabel>{siteName}</masterLabel> | ||
| <redirectToCustomDomain>false</redirectToCustomDomain> | ||
| <referrerPolicyOriginWhenCrossOrigin>true</referrerPolicyOriginWhenCrossOrigin> | ||
| <selfRegPage>CommunitiesSelfReg</selfRegPage> | ||
| <siteType>ChatterNetwork</siteType> | ||
| <urlPathPrefix>{siteUrlPathPrefix}vforcesite</urlPathPrefix> | ||
| </CustomSite> | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Configure Metadata: DigitalExperienceBundle | ||
|
|
||
| ## Purpose | ||
| This configuration file creates a **net-new, default** DigitalExperienceBundle metadata record for a Digital Experience React Site. It is not intended to edit or modify an existing DigitalExperienceBundle record. Use this template only when provisioning a brand-new React site. | ||
|
|
||
| ## File Location | ||
| ``` | ||
| digitalExperiences/site/{siteName}1/{siteName}1.digitalExperience-meta.xml | ||
| ``` | ||
|
|
||
| ## Default Template | ||
| ```xml | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <DigitalExperienceBundle xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
| <label>{siteName}1</label> | ||
| </DigitalExperienceBundle> | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Configure Metadata: DigitalExperienceConfig | ||
|
|
||
| ## Purpose | ||
| This configuration file creates a **net-new, default** DigitalExperienceConfig metadata record for a Digital Experience React Site. It is not intended to edit or modify an existing DigitalExperienceConfig record. Use this template only when provisioning a brand-new React site. | ||
|
|
||
| ## File Location | ||
| ``` | ||
| digitalExperienceConfigs/{siteName}1.digitalExperienceConfig-meta.xml | ||
| ``` | ||
|
|
||
| ## Default Template | ||
| ```xml | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <DigitalExperienceConfig xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
| <label>{siteName}</label> | ||
| <site> | ||
| <urlPathPrefix>{siteUrlPathPrefix}</urlPathPrefix> | ||
| </site> | ||
| <space>site/{siteName}1</space> | ||
| </DigitalExperienceConfig> | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # Configure Metadata: DigitalExperience (sfdc_cms__site) | ||
|
|
||
| ## Purpose | ||
| These configuration files create **net-new, default** DigitalExperience content records (`sfdc_cms__site` type) for a Digital Experience React Site. They are not intended to edit or modify existing DigitalExperience content. Use these templates only when provisioning a brand-new React site. | ||
|
|
||
| The `appContainer: true` and `appSpace` fields in `content.json` are what make this a React site rather than a standard LWR site. The `appSpace` value follows the format `{namespace}__{developerName}` and must match a deployed `WebApplication` metadata record. | ||
|
|
||
| ## File Location | ||
| The DigitalExperience directory contains only `_meta.json` and `content.json`. Do not create any directories other than `sfdc_cms__site` inside the bundle. | ||
|
|
||
| ``` | ||
| digitalExperiences/site/{siteName}1/sfdc_cms__site/{siteName}1/_meta.json | ||
| digitalExperiences/site/{siteName}1/sfdc_cms__site/{siteName}1/content.json | ||
| ``` | ||
|
|
||
| ## Default Templates | ||
| ### `_meta.json` | ||
| ```json | ||
| { | ||
| "apiName": "{siteName}1", | ||
| "path": "", | ||
| "type": "sfdc_cms__site" | ||
| } | ||
| ``` | ||
|
|
||
| ### `content.json` | ||
| ```json | ||
| { | ||
| "type": "sfdc_cms__site", | ||
| "title": "{siteName}", | ||
| "urlName": "{siteUrlPathPrefix}", | ||
| "contentBody": { | ||
| "authenticationType": "AUTHENTICATED_WITH_PUBLIC_ACCESS_ENABLED", | ||
| "appContainer": true, | ||
| "appSpace": "{appNamespace}__{appDevName}" | ||
| } | ||
| } | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Configure Metadata: Network | ||
|
|
||
| ## Purpose | ||
| This configuration file creates a **net-new, default** Network metadata record for a Digital Experience React Site. It is not intended to edit or modify an existing Network record. Use this template only when provisioning a brand-new React site. | ||
|
|
||
| ## File Location | ||
| ``` | ||
| networks/{siteName}.network-meta.xml | ||
| ``` | ||
|
|
||
| ## Default Template | ||
| ```xml | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <Network xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
| <allowInternalUserLogin>false</allowInternalUserLogin> | ||
| <allowMembersToFlag>false</allowMembersToFlag> | ||
| <changePasswordTemplate>unfiled$public/CommunityChangePasswordEmailTemplate</changePasswordTemplate> | ||
| <disableReputationRecordConversations>true</disableReputationRecordConversations> | ||
| <emailSenderAddress>admin@company.com</emailSenderAddress> | ||
| <emailSenderName>{siteName}</emailSenderName> | ||
| <embeddedLoginEnabled>false</embeddedLoginEnabled> | ||
| <enableApexCDNCaching>true</enableApexCDNCaching> | ||
| <enableCustomVFErrorPageOverrides>false</enableCustomVFErrorPageOverrides> | ||
| <enableDirectMessages>true</enableDirectMessages> | ||
| <enableExpFriendlyUrlsAsDefault>false</enableExpFriendlyUrlsAsDefault> | ||
| <enableExperienceBundleBasedSnaOverrideEnabled>true</enableExperienceBundleBasedSnaOverrideEnabled> | ||
| <enableGuestChatter>{enableGuestAccess}</enableGuestChatter> | ||
| <enableGuestFileAccess>false</enableGuestFileAccess> | ||
| <enableGuestMemberVisibility>false</enableGuestMemberVisibility> | ||
| <enableImageOptimizationCDN>true</enableImageOptimizationCDN> | ||
| <enableInvitation>false</enableInvitation> | ||
| <enableKnowledgeable>false</enableKnowledgeable> | ||
| <enableLWRExperienceConnectedApp>false</enableLWRExperienceConnectedApp> | ||
| <enableMemberVisibility>false</enableMemberVisibility> | ||
| <enableNicknameDisplay>true</enableNicknameDisplay> | ||
| <enablePrivateMessages>false</enablePrivateMessages> | ||
| <enableReputation>false</enableReputation> | ||
| <enableShowAllNetworkSettings>false</enableShowAllNetworkSettings> | ||
| <enableSiteAsContainer>true</enableSiteAsContainer> | ||
| <enableTalkingAboutStats>true</enableTalkingAboutStats> | ||
| <enableTopicAssignmentRules>true</enableTopicAssignmentRules> | ||
| <enableTopicSuggestions>false</enableTopicSuggestions> | ||
| <enableUpDownVote>false</enableUpDownVote> | ||
| <forgotPasswordTemplate>unfiled$public/CommunityForgotPasswordEmailTemplate</forgotPasswordTemplate> | ||
| <gatherCustomerSentimentData>false</gatherCustomerSentimentData> | ||
| <headlessForgotPasswordTemplate>unfiled$public/CommunityHeadlessForgotPasswordTemplate</headlessForgotPasswordTemplate> | ||
| <headlessRegistrationTemplate>unfiled$public/CommunityHeadlessRegistrationTemplate</headlessRegistrationTemplate> | ||
| <networkMemberGroups> | ||
| <profile>admin</profile> | ||
| </networkMemberGroups> | ||
| <networkPageOverrides> | ||
| <changePasswordPageOverrideSetting>Standard</changePasswordPageOverrideSetting> | ||
| <forgotPasswordPageOverrideSetting>Designer</forgotPasswordPageOverrideSetting> | ||
| <homePageOverrideSetting>Designer</homePageOverrideSetting> | ||
| <loginPageOverrideSetting>Designer</loginPageOverrideSetting> | ||
| <selfRegProfilePageOverrideSetting>Designer</selfRegProfilePageOverrideSetting> | ||
| </networkPageOverrides> | ||
| <newSenderAddress>admin@company.com</newSenderAddress> | ||
| <picassoSite>{siteName}1</picassoSite> | ||
| <selfRegistration>false</selfRegistration> | ||
| <sendWelcomeEmail>true</sendWelcomeEmail> | ||
| <site>{siteName}</site> | ||
| <siteArchiveStatus>NotArchived</siteArchiveStatus> | ||
| <status>Live</status> | ||
| <tabs> | ||
| <defaultTab>home</defaultTab> | ||
| <standardTab>Chatter</standardTab> | ||
| </tabs> | ||
| <urlPathPrefix>{siteUrlPathPrefix}vforcesite</urlPathPrefix> | ||
| <welcomeTemplate>unfiled$public/CommunityWelcomeEmailTemplate</welcomeTemplate> | ||
| </Network> | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is also present in @scottmo 's PR: #27
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please follow the recommended naming recommendation for skills
Just to follow consistent pattern which we are about to do for all other existing type is
generating*i.e.generating-experience-lwr-siteThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MadMagyar92 : Is this PR still needed? If so, can you follow @hsinghbisht-sfdc 's comment above and fix the name, or pull in the latest changes (which include renamed skills)? Else, please close this.