cicd-for-experience-cloud

CI/CD pipeline patterns for Experience Cloud sites — the layer between sfdx-project metadata deploys and a working production site. Covers GitHub Actions / Jenkins / GitLab pipeline shapes for ExperienceBundle / DigitalExperienceBundle deploys, BrandingSet + ExperiencePropertyTypeBundle promotion, guest-user permission-set automation, custom-domain / CDN binding scripts, and the ordering rules that make the difference between a clean deploy and a half-applied site. NOT for the metadata-shape details (use devops/experience-cloud-deployment-dev), NOT for generic SFDX CI/CD (use devops/sfdx-cicd-pipeline).

Best use case

cicd-for-experience-cloud is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

CI/CD pipeline patterns for Experience Cloud sites — the layer between sfdx-project metadata deploys and a working production site. Covers GitHub Actions / Jenkins / GitLab pipeline shapes for ExperienceBundle / DigitalExperienceBundle deploys, BrandingSet + ExperiencePropertyTypeBundle promotion, guest-user permission-set automation, custom-domain / CDN binding scripts, and the ordering rules that make the difference between a clean deploy and a half-applied site. NOT for the metadata-shape details (use devops/experience-cloud-deployment-dev), NOT for generic SFDX CI/CD (use devops/sfdx-cicd-pipeline).

Teams using cicd-for-experience-cloud should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/cicd-for-experience-cloud/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/devops/cicd-for-experience-cloud/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/cicd-for-experience-cloud/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How cicd-for-experience-cloud Compares

Feature / Agentcicd-for-experience-cloudStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

CI/CD pipeline patterns for Experience Cloud sites — the layer between sfdx-project metadata deploys and a working production site. Covers GitHub Actions / Jenkins / GitLab pipeline shapes for ExperienceBundle / DigitalExperienceBundle deploys, BrandingSet + ExperiencePropertyTypeBundle promotion, guest-user permission-set automation, custom-domain / CDN binding scripts, and the ordering rules that make the difference between a clean deploy and a half-applied site. NOT for the metadata-shape details (use devops/experience-cloud-deployment-dev), NOT for generic SFDX CI/CD (use devops/sfdx-cicd-pipeline).

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# CI/CD for Experience Cloud

The pipeline layer that turns a versioned ExperienceBundle into a working
production site. Generic SFDX CI/CD gets you 80 % of the way there; the
last 20 % is Experience-Cloud-specific — metadata ordering rules, theme
promotion, guest-user permission-set automation, and the custom-domain
binding that lives outside Metadata API entirely.

What this skill is NOT. The shape of `ExperienceBundle` /
`DigitalExperienceBundle` metadata, the CMS Managed Content exclusion,
and the per-bundle deploy mechanics live in
`devops/experience-cloud-deployment-dev`. Generic SFDX CI/CD patterns
(scratch org strategy, source tracking, package versioning) live in
`devops/sfdx-cicd-pipeline`. This skill is the Experience-Cloud-specific
*pipeline-tooling* layer between them.

---

## Before Starting

- **Confirm the metadata API version.** `ExperienceBundle` is the older
  shape; `DigitalExperienceBundle` is the v58+ shape for LWR sites.
  Older sites may still ship as `ExperienceBundle`. The pipeline must
  match the source-org's bundle type.
- **Decide who owns CMS content promotion.** Salesforce CMS Managed
  Content is *not* fully covered by the SFDX CLI / Metadata API.
  Pipelines that assume "deploy bundles, content goes with them" will
  ship broken sites. Either treat CMS content as runtime-config
  (admins promote separately) or build a custom CMS-content-export
  step.
- **Identify every dependency the bundle deploy needs in place first.**
  Custom objects, fields, profiles, permission sets, the Network
  metadata that defines the site itself — all must exist in the
  target before the bundle deploys. Order matters.
- **Decide the guest-user model.** Permission-set assignment to the
  guest user is a one-time-per-org operation that bundle deploys do
  NOT redo. If the pipeline doesn't include explicit guest-user
  reconciliation, the first guest after a fresh deploy will see "no
  access" errors that nobody knows how to debug.

---

## Core Concepts

### The four metadata-ordering rules

Experience Cloud deploys are non-trivially ordered. The pipeline must
sequence:

1. **Foundation metadata first.** Custom objects, custom fields,
   permission sets, profiles, profile field-level security. The
   ExperienceBundle references these; if missing, the deploy fails.
2. **`Network` metadata.** Defines the Site / Community itself
   (URL prefix, login behavior, accessibility). Required before any
   ExperienceBundle that targets it.
3. **`ExperienceBundle` / `DigitalExperienceBundle`.** The bundle
   itself — pages, components, properties, navigation menus.
4. **`BrandingSet` and `ExperiencePropertyTypeBundle`.** Theme
   tokens (colors, fonts, logos), component property types. Often
   shared across multiple sites — promote *after* the bundles that
   reference them, but the BrandingSet metadata itself can deploy in
   the same package.

CMS Managed Content (articles, images, video assets) is **outside this
ordering** — handled separately because it doesn't ship via SFDX.

### Guest-user permission-set automation

Every Experience Cloud site has a guest-user profile auto-provisioned
when the site is created. Permissions on the guest user control what
anonymous visitors can read. The pipeline must:

- Assign required permission sets to the guest user (most common:
  read-access to lookup objects the site queries).
- Re-apply permission sets after any production refresh / sandbox
  copy that resets the guest user.
- Validate guest-user permissions match a known baseline before
  promoting through environments.

Salesforce CLI does not have a single "set up the guest user" command.
The automation pattern is a small sf-cli wrapper script (or Apex
anonymous block) that assigns the relevant permission sets to the
site's guest user, idempotent on re-run.

### Custom-domain / CDN binding

Production Experience Cloud sites usually live on a custom domain
(`portal.example.com`, not `example.my.site.com`). Two pieces:

1. **Salesforce-side:** Setup → Domains → register the custom domain
   → bind to the site. Metadata-deployable via `CustomDomain` /
   `CustomSite` types but with caveats — the domain registration
   step requires DNS verification that's not pipeline-automatable on
   the Salesforce side.
2. **DNS-side:** CNAME the custom domain at the Salesforce-supplied
   target (or a CDN that fronts it). Owned by the DNS team, not
   Salesforce.

The pipeline coordinates these: deploy the Salesforce-side metadata,
emit the DNS targets to a known location, the DNS team applies them.
Many pipelines stop at "metadata deployed" and miss that the site
isn't reachable until DNS propagates — explicit DNS-confirmation gate
prevents that.

### Theme reuse via BrandingSet

`BrandingSet` defines tokens (primary color, font family, logo
references) that themes consume. A single BrandingSet referenced from
multiple sites is the right pattern for multi-site brand consistency.
Pipeline implication: BrandingSet promotion is a separate concern from
bundle promotion — same metadata package can carry both, but the
theme team's promotion cadence often differs from the
site-feature-team's cadence.

---

## Common Patterns

### Pattern A — GitHub Actions pipeline for a single LWR site

```yaml
# .github/workflows/experience-cloud-deploy.yml
name: deploy-experience-cloud-site

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: install sf cli
        run: npm install -g @salesforce/cli

      - name: authenticate
        env:
          SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL }}
        run: |
          echo "$SFDX_AUTH_URL" > ./auth.txt
          sf org login sfdx-url --sfdx-url-file ./auth.txt --alias prod
          rm ./auth.txt

      # 1. Foundation: objects/fields/permission-sets the bundle depends on.
      - name: deploy foundation metadata
        run: sf project deploy start
              --source-dir force-app/main/default/objects
              --source-dir force-app/main/default/permissionsets
              --target-org prod

      # 2. Network metadata (defines the site itself).
      - name: deploy network metadata
        run: sf project deploy start --source-dir force-app/main/default/networks --target-org prod

      # 3. The ExperienceBundle / DigitalExperienceBundle itself.
      - name: deploy experience bundle
        run: sf project deploy start --source-dir force-app/main/default/experiences --target-org prod

      # 4. BrandingSets last — they reference bundle artifacts.
      - name: deploy branding sets
        run: sf project deploy start --source-dir force-app/main/default/brandingSets --target-org prod

      # 5. Guest-user permission reconciliation.
      - name: assign guest-user permsets
        run: bash scripts/assign-guest-permsets.sh prod

      # 6. Smoke test — confirm site loads, anonymous read works.
      - name: smoke test
        run: bash scripts/smoke-test-site.sh prod

      # 7. Emit DNS targets for the DNS team (if domain not yet bound).
      - name: emit DNS targets
        run: bash scripts/emit-dns-targets.sh prod > dns-targets.txt
      - uses: actions/upload-artifact@v4
        with:
          name: dns-targets
          path: dns-targets.txt
```

The seven-step shape: foundation → Network → bundle → BrandingSet →
guest-user → smoke → DNS-emit. Drop or reorder a step and the deploy
either fails noisily (good) or appears to succeed but leaves the site
broken (bad — see Gotchas).

### Pattern B — Multi-site theme promotion

**When to use.** A BrandingSet shared by 4+ sites (corporate brand),
promoted on its own cadence (theme team owns it) separate from the
per-site feature releases.

**Approach.** Two pipelines, one repository:

- `branding-pipeline.yml` — deploys `force-app/main/default/brandingSets/`
  alone. Triggers on changes to that directory. Runs against all
  consuming orgs.
- `site-pipelines/<site>.yml` — deploys per-site bundles. Trigger on
  per-site directory changes.

The pipelines are independent; site bundles reference the BrandingSet
by API name. Coordination happens via the API name being stable —
renaming a BrandingSet is a coordinated migration across every site
that consumes it.

### Pattern C — Guest-user permission-set baseline validator

**When to use.** Production refreshes / sandbox copies that reset
guest-user permissions. Without a validator, you discover the
regression when a customer reports "site says no access".

```bash
#!/bin/bash
# scripts/validate-guest-permsets.sh
set -eu
TARGET=$1
EXPECTED_PERMSETS="Site_Public_Read,Site_Lookup_Access"

# Find the site's guest user.
GUEST_USER=$(sf data query --query \
    "SELECT Username FROM User WHERE Profile.Name LIKE '%Site Profile%' AND IsActive = TRUE LIMIT 1" \
    --target-org "$TARGET" --json | jq -r '.result.records[0].Username')

# Check assigned permission sets.
ASSIGNED=$(sf data query --query \
    "SELECT PermissionSet.Name FROM PermissionSetAssignment WHERE Assignee.Username = '$GUEST_USER'" \
    --target-org "$TARGET" --json | jq -r '.result.records[].PermissionSet.Name' | sort | tr '\n' ',')

# Compare against baseline.
for ps in ${EXPECTED_PERMSETS//,/ }; do
    if ! echo "$ASSIGNED" | grep -q "$ps"; then
        echo "MISSING guest permset: $ps"
        exit 1
    fi
done
echo "OK: guest user has all expected permsets"
```

Run as a CI gate on every promotion. Cheap; catches the regression
before customers do.

---

## Decision Guidance

| Situation | Approach | Reason |
|---|---|---|
| First Experience Cloud pipeline for a new site | **Pattern A** (single-site 7-step pipeline) | Standard shape; covers ordering, guest user, DNS coordination |
| Multi-site brand consistency | **Pattern B** (theme pipeline + per-site pipelines) | BrandingSet promotion has a different cadence than site features |
| Refreshed sandbox loses guest permissions | **Pattern C validator** as CI gate | Catches the regression automatically |
| LWR site (modern, post-API v58) | `DigitalExperienceBundle` deploys | LWR-specific bundle type |
| Aura-based site | `ExperienceBundle` deploys | Older bundle type |
| Hybrid Aura + LWR site (uncommon) | Both bundle types in the package | Each component lives in its own bundle |
| Custom domain not yet DNS-bound | Pipeline emits DNS targets; gate on confirmation | Don't promote past "metadata deployed" until the site is reachable |
| CMS Managed Content needed in target | Separate CMS-content-export step (NOT SFDX) | CMS isn't covered by Metadata API |
| Generic SFDX CI/CD without Experience-Cloud specifics | **Use `devops/sfdx-cicd-pipeline`** | Don't reinvent the SFDX layer |
| Bundle metadata details / shape | **Use `devops/experience-cloud-deployment-dev`** | This skill is pipelines, not bundle internals |

---

## Recommended Workflow

1. **Identify bundle type** (Aura `ExperienceBundle` vs LWR `DigitalExperienceBundle`). Pipeline source paths and deploy commands differ.
2. **Inventory dependencies** (objects, fields, profiles, permission sets, Network metadata) and order them as foundation → network → bundle → branding.
3. **Build the pipeline** following Pattern A's seven-step shape.
4. **Add guest-user reconciliation** as an explicit step. Don't assume it's automatic.
5. **Add the guest-user permset validator** (Pattern C) as a CI gate.
6. **Coordinate DNS** with the DNS team — pipeline emits targets, DNS team applies, gate the next promotion on DNS-confirmation.
7. **Plan CMS-content promotion separately** if the site uses CMS Managed Content.

---

## Review Checklist

- [ ] Bundle type matches the source-org's site (ExperienceBundle vs DigitalExperienceBundle).
- [ ] Foundation metadata (objects, fields, permission sets) deploys *before* the bundle.
- [ ] Network metadata deploys before the ExperienceBundle that targets it.
- [ ] BrandingSet promotion is sequenced with the bundles that reference it.
- [ ] Guest-user permission-set assignment is an explicit pipeline step.
- [ ] Guest-user permset validator runs as a CI gate post-deploy.
- [ ] CMS Managed Content promotion is handled (or explicitly excluded with rationale).
- [ ] Custom-domain DNS targets are emitted and the DNS team has a known follow-up.
- [ ] Smoke test validates the site loads and anonymous read works.

---

## Salesforce-Specific Gotchas

1. **CMS Managed Content is not covered by SFDX.** Pipelines that assume "deploy and the content comes too" ship broken sites. (See `references/gotchas.md` § 1.)
2. **Guest-user permission sets reset on sandbox refresh.** Without a CI step that re-applies them, the first guest after refresh sees access errors. (See `references/gotchas.md` § 2.)
3. **Network metadata must deploy before the ExperienceBundle** that targets it. Reverse order produces a deploy that succeeds-but-doesn't-work. (See `references/gotchas.md` § 3.)
4. **`ExperienceBundle` (Aura) and `DigitalExperienceBundle` (LWR) are different metadata types.** Pipeline source paths differ; mixing them in a single deploy is fine but the paths and target sites must match. (See `references/gotchas.md` § 4.)
5. **Custom-domain registration requires DNS verification** that's not pipeline-automatable on the Salesforce side. The pipeline must coordinate with the DNS team. (See `references/gotchas.md` § 5.)
6. **`ExperienceBundleSettings` must be enabled in the target org** before any ExperienceBundle deploys. First-time setup catches this once. (See `references/gotchas.md` § 6.)
7. **Renaming a BrandingSet API name breaks every site that references it.** Treat as a coordinated migration. (See `references/gotchas.md` § 7.)

---

## Output Artifacts

| Artifact | Description |
|---|---|
| Pipeline definition | `.github/workflows/*.yml`, Jenkinsfile, GitLab CI YAML, etc. — the seven-step shape |
| Guest-user assignment script | sf-cli wrapper that assigns permission sets to the site guest user |
| Guest-user validator | CI gate that confirms the guest user has the expected permission sets |
| DNS-target emitter | Post-deploy script that surfaces the Salesforce-supplied CNAME target for the DNS team |
| Smoke-test script | Confirms the site URL responds 200 and the homepage renders for an anonymous visitor |

---

## Related Skills

- `devops/experience-cloud-deployment-dev` — bundle metadata internals (this skill ends where that one starts).
- `devops/sfdx-cicd-pipeline` — generic SFDX CI/CD; this skill assumes those primitives are in place.
- `admin/experience-cloud-admin-designer` — site design / configuration; this skill is the deploy half.
- `security/guest-user-security` — what permissions the guest user *should* have (vs this skill which is about how the pipeline applies them).
- `architect/experience-cloud-licensing-model` — license-model decisions upstream of the pipeline.

Related Skills

experience-cloud-security

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when configuring access controls, sharing, or site security for authenticated or guest Experience Cloud (community) users: external OWD, Sharing Sets, Share Groups, CSP, clickjack protection, guest user record access. NOT for internal sharing model configuration (use sharing-and-visibility).

headless-experience-cloud

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building custom frontends (React, Vue, mobile, static sites) that consume Salesforce CMS content via the Connect REST API headless delivery endpoint. Triggers: 'headless Salesforce CMS', 'deliver CMS content to external frontend', 'React app Salesforce content API', 'custom frontend Experience Cloud data', 'CMS delivery channel API'. NOT for standard Experience Builder site development. NOT for CMS Connect (3rd-party CMS federation into Experience Builder). NOT for Experience Cloud LWC components rendered inside a site.

experience-cloud-search-customization

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring or extending search on an Experience Cloud site — covering Search Manager scope configuration, LWR vs Aura search component selection, federated search setup, guest user search access, and custom search result components. NOT for SOSL/SOQL query development. NOT for internal Salesforce global search or Einstein Search for agents.

experience-cloud-multi-idp-sso

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring multiple identity providers (OIDC and/or SAML) on a single Experience Cloud site or across tenant-specific portals in the same org — covering auth provider registration, Start SSO URL routing, Federation ID mapping, RegistrationHandler implementation, and simultaneous SP+IdP topology. Trigger keywords: multiple identity providers Experience Cloud, multi-tenant SSO community portal, vendor and citizen portal same site, OIDC SAML both on login page, tenant-specific login routing community. NOT for internal Salesforce employee SSO configuration. NOT for single auth provider setups — see experience-cloud-authentication for basic SSO.

experience-cloud-lwc-components

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building custom LWC components for Experience Cloud (Experience Builder sites, LWR portals, Aura-based communities). Covers community context imports, guest user Apex access patterns, navigation API differences between LWR and Aura, and JS-meta.xml target configuration for Experience Builder exposure. NOT for internal LWC components deployed to Lightning App Builder or standard record pages (see lwc/lwc-development). NOT for Aura community components. Trigger keywords: build LWC for Experience Cloud, custom component community portal LWC, guest user LWC component, community context import salesforce, lightningCommunity target, @salesforce/community, guest Apex.

experience-cloud-authentication

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building custom login pages, social SSO flows, self-registration flows, or passwordless OTP login for Experience Cloud (community) sites. Trigger keywords: custom login page Experience Cloud, social SSO community portal, passwordless login Experience Cloud, self-registration custom flow, headless authentication community, auth provider OIDC SAML site. NOT for internal SSO configuration (use identity/sso skills). NOT for standard username/password authentication with no customization.

experience-cloud-api-access

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring or troubleshooting API access for Experience Cloud external users and guest users: guest user Apex data access, Customer Community Plus or Partner Community REST/SOAP API access, external user OAuth scopes, and sharing enforcement on API responses. Trigger keywords: Experience Cloud API access external user, community user REST API, guest user API limits, Customer Community API permissions, external user OAuth. NOT for internal Salesforce API authentication, non-community OAuth flows, or internal user API security.

net-zero-cloud-setup

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring Salesforce Net Zero Cloud — including Scope 1/2/3 emission source modeling via the StnryAssetCrbnFtprnt / VehicleAssetCrbnFtprnt / Scope3CrbnFtprnt object families, emission factor library setup (EmssnFctr / EmssnFctrSet), DPE-driven carbon calculation jobs, supplier engagement scoring, and CSRD / ESRS / TCFD disclosure pack mapping. Triggers on: Net Zero Cloud setup, Sustainability Cloud carbon accounting, Scope 1 2 3 emissions Salesforce, emission factor library, supplier engagement Net Zero, ESG disclosure pack mapping. NOT for ESG content scoring (use Marketing Cloud), NOT for general financial reporting (use Accounting Subledger), NOT for energy-only utility billing (use Energy & Utilities Cloud).

manufacturing-cloud-setup

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring Salesforce Manufacturing Cloud — including Sales Agreement setup, Account-Based Forecasting (ABF) recalc jobs, run-rate management, Rebate Management programs, channel inventory tracking via Channel Revenue Management, and Group Membership / OrderItem-to-SalesAgreement reconciliation. Triggers on: Manufacturing Cloud setup, Sales Agreement Salesforce, account-based forecast recalculation, run rate manufacturing, rebate program setup, channel revenue management. NOT for general Sales Cloud opportunity-to-order flow (use standard Opportunity / Order), NOT for Field Service install-base management (use FSL skills), NOT for Automotive Cloud dealer modeling (use automotive-cloud-setup).

data-cloud-zero-copy-federation

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring or troubleshooting Data Cloud Zero Copy / Lakehouse Federation against Snowflake, Databricks, BigQuery, or Redshift — including external Data Lake Object setup, query semantics through federation, refresh and cache behavior, and choosing federation versus physical ingestion. Triggers on: Data Cloud federated DLO setup, query latency against external warehouse, Snowflake/Databricks/BigQuery integration with Data Cloud, federation vs ingestion decision. NOT for physical Ingestion API streaming/bulk patterns (use data-cloud-integration-strategy), not for CRM Analytics external connectors (use analytics-external-data), not for outbound Data Cloud activation to external systems (use data-cloud-activation-development).

data-cloud-query-api

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when querying unified profile data, calculated insights, or Data Lake Objects from Data Cloud using ANSI SQL via the Query V2 or Query Connect APIs. Triggers on: SQL queries against Data Cloud, querying unified individuals, querying DMOs via API, paginating large Data Cloud result sets. NOT for SOQL queries against standard Salesforce objects, not for Data Cloud segment filtering in the UI, not for vector/semantic search (use data-cloud-vector-search-dev).

data-cloud-integration-strategy

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when designing or troubleshooting the data pipeline strategy for connecting source systems to Data Cloud — including ingestion API pattern selection (streaming vs. batch), connector type decisions, DSO-to-DLO-to-DMO pipeline lag, and lakehouse federation patterns. Triggers on: Data Cloud ingestion API setup, streaming vs batch connector decision, Data Cloud connector types, MuleSoft Direct for Data Cloud, data pipeline lag for segmentation. NOT for standard Salesforce integration patterns (use integration-patterns skill), not for querying Data Cloud once data is ingested (use data-cloud-query-api), not for configuring standard admin connectors through the UI only.