experience-ui-bundle-deploy

MUST activate when the project has a uiBundles/*/src/ directory and the task involves deploying to an org or post-deploy org setup. Deploys a UI bundle app and runs ordered setup: org auth, build, metadata deploy, permission-set and role assignment, Experience Cloud self-registration, social login /

By forcedotcom · 4,916 installs

npx skills add forcedotcom/sf-skills --skill experience-ui-bundle-deploy

Source repository · Upstream listing

Deploying a UI Bundle App Deploy order is load bearing: a step's output is the next step's precondition (deploy before schema fetch; permissions before schema fetch; role/self reg before the schema the guest user must see). This is the canonical setup sequence, ported from the reference org setup.mjs . The org setup.mjs line citations in references/ are port provenance (why each rule exists) pointing at that external reference script — not files shipped with this skill — so you don't need to open them to run the steps. Run each step in order. Every optional step is presence driven : if its convention file is absent, no op cleanly and move on — do not fabricate config. For the two destructive/expensive steps (self registration, data import), ask the user before running . Inputs to gather up front Read these from the project; ask the user only for what's missing: Target org — alias/username for target org . Ask if not obvious. Source root — run scripts/get source root.sh to resolve the metadata source dir from sfdx project.json ( packageDirectories[0].path + /main/default ). It exits non zero if the project file is missing or malformed. Never hardcode force app/main/default . org setup.config.json (optional) — drives permset assignment, role, self registration, and social login. Absent keys mean "skip that step". Exception: if the file is missing but permissionsets/ has permsets to assign, don't silently skip — scaffold the config or gather equivalent inputs (see step 4). data plan.json (optional, in the project's data/ dir) — presence enables the data step. Step 1 — Org authentication (always) Unconditional precondition; cannot be skipped. If the org is already connected ( sf org display target org <org json succeeds), no op. Otherwise: A failed login aborts the whole setup before deploy. Step 2 — Pre deploy UI bundle build Build every UI bundle so dist/ exists before metadata deploy (UI bundle entities deploy the built output). For each bundle dir under uiBundles/ : Run when deploying UI bundles and dist/ is missing or source changed. Step 3 — Deploy metadata If self registration is configured: 1. Deploy license pre check first (see references/license checks.md ) — it blocks the deploy with a clear, license naming message instead of a cryptic failure. 2. Add the self reg profile to networkMemberGroups on the local source — apply Edit A of assets/network selfreg xml recipe.md . This must happen before this deploy so the profile ships as a recognised site member; do NOT deploy the network file on its own here (this deploy ships it). Best effort and idempotent — skip if already a member. Then deploy the whole project (all metadata) by pointing source dir at the resolved source root: <sourceRoot is the value from scripts/get source root.sh (e.g. force app/main/default ). Always pass source dir . Do NOT run bare sf project deploy start with no path: that command relies on source tracking to decide what to deploy, and on an org without source tracking (most non scratch orgs) it aborts with "This org does not have source tracking enabled … specify the files or a manifest to deploy." Passing source dir deploys the same full set on both source tracked and non tracked orgs and never emits that hint. If the deploy reports conflicts on a source tracked org, re run with ignore conflicts — do NOT roll back or reduce the deployed set. Do NOT hand build a package.xml , assemble a metadata dir mdapi zip, or otherwise convert to metadata format — none of that is needed and it is not part of this flow. Timeout 180s. Must complete before permission assignment and schema fetch — objects, fields, and permission sets appear in the org only after deploy. Step 3b — Set the site logout URL (config gated) Run only when org setup.config.json has a top level logoutUrl . If absent, no op cleanly and say so. Non destructive and idempotent — no ask needed. Runs here, after the deploy (not folded into it) because the platform rejects a relative logout URL ( "The logout page URL must be an absolute URL." ), and a shipped site relative path (e.g. /propertyrentalapp/ ) is resolved to absolute against the site's Experience Cloud origin — which only exists once the site is deployed. Why it matters: a site with no <logoutUrl sends a logging out member to the org default site login page — in a multi site org that's a different community, so Sign Out lands on the wrong site's login page. Setting it steers logout back to this site (reload as Guest). Steps: 1. Read logoutUrl from config; absent → skip. 2. Derive the site — scripts/derive site name.sh (single .network meta.xml ; skip if zero/ambiguous). 3. Resolve, set, and deploy — one command. Invoke the helper, which resolves the value to an absolute URL (site relative → matched against the community siteUrl path , never guessing), writes <logoutUrl idempotently in the canonical position, and deploys only that file: Best effort: the helper exits 0 on success or already set, and 3 on a recoverable skip (network file missing, origin unresolvable, XML special char, or deploy failure). Treat exit 3 as a loud skip, not a setup failure — continue the rest of setup and tell the user to set the logout URL manually in the site's Administration settings. Usage, exit code contract, and port provenance: references/logout url.md . Step 4 — Assign permission sets Discover permission sets under <packageDir /main/default/permissionsets/ . If none exist and none were passed explicitly, skip. If permsets exist but org setup.config.json is missing, do NOT silently skip. A missing config makes every discovered permset resolve to skip , so nothing gets assigned and the later GraphQL schema comes back incomplete (the caller lacks FLS). Instead, help the user supply the assignments — either scaffold org setup.config.json from assets/org setup.config.template.json or gather the per permset assignee inputs for a one off run. Full schema + scaffolding flow: references/config scaffold.md . Confirm intent before writing the file or assigning — don't fabricate assignees. Otherwise assign each per its config assignee ( org setup.config.json → permsetAssignments ), where each assignee is one of currentUser , guestUser , or skip (default skip ): currentUser — omit on behalf of . guestUser — resolve the site's guest username first (see the guest user section in references/self registration.md ). If the site can't be derived or no guest user resolves, skip that permset and record the reason — don't abort the others. Treat "Duplicate … PermissionSet" and "not found … target org" as skips, not failures. Required so GraphQL introspection returns the correct schema (the caller needs FLS on custom fields). Step 5 — Assign role (config gated) Run only when org setup.config.json has role: { assignee: "currentUser", roleName: "<UserRole " } . Assigning a role to the current user is what lets Experience Cloud self registration work. Idempotent — skip if the user already has a role. Detail + exact queries: references/role assignment.md . Step 6 — Enable self registration (config gated) — ask first Run only when org setup.config.json has selfRegistration: { selfRegProfile, accountName } . Ask the user before running. Sequence (full detail in references/self registration.md ): 1. License pre check (soft skip) — if the org lacks a seat on the profile's license, warn and skip; it is not a failure. See references/license checks.md . 2. Derive the site — run scripts/derive site name.sh ; it outputs the site name (the base name of the single .network meta.xml ) or exits non zero when zero or more than one exist (ambiguous — stop). 3. Flip self reg on + redeploy the network file — apply Edit B of assets/network selfreg xml recipe.md (set selfRegistration=true , inject <selfRegProfile ), then redeploy only that one file. Idempotent — skip both if already enabled. (Edit A, the member group add, already happened in step 3.) 4. Create the Account + NetworkSelfRegistration — apply assets/network selfreg.apex (idempotent; both are query then create; run 4a and 4b as two separate sf apex run invocations). Step 6b — Enable social login (config gated) Run only when org setup.config.json has a socialLogin block. If the block is absent, loadSocialLoginConfig returns null and the step is hidden — no op cleanly and say so. This step is non destructive and idempotent (it only adds missing links/members), so — unlike self registration and data import — it does not require asking first. This links the site's configured Auth Providers (OAuth) and SAML SSO configs to the site so the built in Social Login component renders their buttons on the React login page. On React (Site Container) sites the SSO admin UI is hidden, so the linking is done programmatically via AuthConfig / AuthConfigProviders records — you cannot do it by clicking through Setup. Full detail, sub steps, and port provenance: references/social login.md . Config shape (see references/config scaffold.md for the full schema): Sequence (mirrors reference org setup.mjs main() social login step, which runs after self registration and before the data/GraphQL steps): Apply the assets/ templates verbatim (like the self reg/data steps) — full runnable commands for each sub step are in references/social login.md : 1. Derive the site — run scripts/derive site name.sh (single .network meta.xml ; stop if zero/ambiguous). Social login needs the site to resolve its AuthConfig . 2. Enable "Allow standard external profiles" — deploy assets/Communities.settings meta.xml via Metadata API (from a throwaway minimal project; see the reference). Required so the SSO registration handler can create users on standard community profiles; without it auth providers fail user insert with FIELD INTEGRITY EXCEPTION . A "already active" warning is a non fatal skip. 3. Link Auth Providers to the site AuthConfig — run assets/social login auth providers.apex verbatim (substitute <siteName , <ProviderNamesList , <ApiVersion ) to create the missing AuthConfigProviders junctions, then read its DEBUG lines (table in the reference). All or nothing: if any configured authProviderNames entry has no matching AuthProvider (OAuth) or SamlSsoConfig (SAML) record, it emits MISSING PROVIDERS and links nothing — create/fix them in Setup first. Already linked providers are skipped (idempotent). 4. Add the community member profile to NetworkMemberGroup — resolve the Network + Profile Ids and create the membership if absent ( sf data commands in the reference). Without it, SSO registered users hit NO ACCESS: User was not authorized for the community . 5. (Optional) Assign communityUserPermset to community users — only when configured. Grants ApiEnabled so getCurrentUser() ( /chatter/users/me ) works for SSO created users. IMPORTANT: A socialLogin block present but skipped is a silent failure trap — the app deploys fine, but no social login buttons ever appear on the login page and there is no error explaining why. Do not silently skip: run the step when the block is present, or state clearly that it was absent. Step 7 — Data import (presence driven) — ask first Run scripts/find data plan.sh first. If it exits non zero, skip this step — do not prompt and do not error; just move on to step 8 (a brief "no data plan, skipping data import" note is fine). There is nothing to import without a plan. On success it prints the plan's path (it searches recursively, so both a project root data/ and a <packageDir /main/default/data/ lay