It's quite a long journey to work out what metadata you want to package in 2GP since you have to manually add all those dependency metadata items for yourself. Since Salesforce doesn't yet provide documentation covering this, I've reproduced here what I posted on the Partner Forums after weeks of slow progress.
To succeed in creating a no-namespace, unlocked package for a Digital Experience:
- Select the right "tree" of related metadata.
- Don't assume that suggestions as to how to achieve certain things, such as including profiles in the unlocked package, will work because these don't seem to function as you might hope.
- It's worth including prefixes on API names for clarity as to what metadata comes from the package and what does not (since it may be no-namespaced).
- Whatever you do, there will be some post-installation manual activities to perform.
I started with the Build Your Own template to make sure I only had the elements I was interested in. Using a different template MAY change your packaging experience.
Let's take a look at the metadata. For the digital experience itself, you likely need:
- contentassets - for the images included in the experience "pages". To function correctly when installed from the unlocked package, these appear to need to be marked as visible to unauthenticated users (despite not being on guest accessible pages). Without this broken image links are shown in the rendered page.
- email - without ensuring to create duplicates of the "standard" email templates you cannot successfully package the site (the references don't get resolved). Make sure to prefix the names of the duplicates (like you prefix everything else) to make it clear it is part of the packaged metadata.
- experiences - the experience bundle itself, lock, stock and barrel.
- flows - any flows you use in the experience.
- layouts - any layouts for object types you have lists, headers or details for in your experience "pages".
- lwc - any bespoke LWCs used in the experience "pages".
- navigationMenus - all navigation options you explicitly use in your experience.
- networks - the network equivalent to your experience bundle.
- permissionsets - the permission set(s) relevant to community users who will use the experience.
- profiles - that you want for use with your experience bundle (see later).
- quickActions - any lightning quick actions you use in the layouts included.
- sites - the site equivalent to your experience bundle. Even though this contains org-specific property values, it appears that Salesforce is smart enough to ignore these values and to replace them with values appropriate to the target org. NB: This is "CustomSite" in the Metadata Coverage Report.
- staticresources - a way to "package" the login branding icon (see later).
(NB: I included other metadata in this package as well, such as custom fields, but that's not important here.)
To do this development, make sure to include the following in your project-scratch-def.json
's settings:
"experienceBundleSettings": {
"enableExperienceBundleMetadata": true
},
"communitiesSettings": {
"enableNetworksEnabled": true
}
You additionally need the following added to "features" in project-scratch-def.json
:
PublishAuraExpBuilderBasedSna
for Aura-based experiences
PublishExpBuilderBasedSna
for LWR-based experiences
Things that you CANNOT package are:
- networkBranding - this metadata type isn't supported for any form of packaging (see "NetworkBranding" in the Metadata Coverage Report). This means there is a post-installation activity for the admin to go set the branding up for login.
- sharingSets - despite there being documented means to include this in an no-namespaced, unlocked 2GP, if I include these in the package I get "field integrity exception" errors during installation.
Strangely (and I'm sure there's some documented reason that I failed to locate) when I install the no-namespace, unlocked package on a scratch org that has all the various licenses such as "Customer Community", all my packaged Profiles for these licenses fail to materialize on the org on which the package is installed. This is likely why the "field integrity exception" errors were happening when I initially included these profiles in the network's "networkMemberGroups" and why sharingSets have issues. I have, therefore, switched to using permission set membership only and dropped the sharing sets from the package.
Because not everything can be packaged, the admin has a number of post-installation activities to perform:
- Create all required Profiles (for page layout assignments required for the object types used in the experience "pages").
- In the Setup > Digital Experience > Settings, create any necessary Sharing Sets for the above profiles. For me, since I expose Contact and its master detail children I had to create a sharing set against "Account" to grant access "User:Contact.Account = Account:Id" as "Read/Write" since Contact OWD sharing is typically Controlled by Parent on our orgs.
- In Setup > Digital Experience > All Sites, select the Workspaces for the packaged experience then select the Administration card:
- Select "Login & Registration" and set the logo, colours and footer text. This is where we ensure the logo image has been included as a static resource; the admin must first download the static resource and then can re-upload it through this UI. (I didn't try to use a URL-based logo.)
- Select "Members" and add any required Profiles, if you use Profile-based (instead of Permission Set-based) membership. (We switched to using perm set based membership, which reduces friction in setting up the package and removes this post-installation step.)
At the end of all this, I have a functional Digital Experience on my org, mostly coming from the no-namespace unlocked package.
There is an alternative approach that seems favoured by the Salesforce TEs, which is to package a Community Template created from the Digital Experience, but for me this:
- Means the admin has more work to do after installation of the package.
- Doesn't support fixes for, and updates to, the Digital Experience by simply installing them; the same fixes/updates must be reproduced manually.
- Makes the packaging more complex since you must separately manage the source Digital Experience from which the packaged template is subsequently generated. Here you need to have multiple package directories, with just the template being in the one for packaging and the source "Digital Experience" metadata appearing in a separate one. This also has the effect of either requiring the dev to pull (or retrieve) the template metadata from a scratch org (if you don't store this metadata in git) or effectively storing generated code in git alongside what it is generated from (which is an anti-pattern). NB: There's a whole set of different metadata components for a template that I'm not covering here.
Obviously having an "upgradable" Digital Experience has its downsides; local changes to the same metadata can be lost when the package is upgraded on the org - this suggests a cloning exercise where post-installation modification is desired, if there is a plan to later upgrade. This does, at least, allow selective (if rather manual) inclusion of updates into the cloned metadata.
NB: I somehow created two Q&As for this, so see also this Q&A.
You may like to watch this Salesforce Interchange episode on this topic too.