Skip to content

fix: digitalExperiences create files to right folders @W-20967044@#1680

Merged
mshanemc merged 3 commits into
mainfrom
d/W-20967044
Feb 10, 2026
Merged

fix: digitalExperiences create files to right folders @W-20967044@#1680
mshanemc merged 3 commits into
mainfrom
d/W-20967044

Conversation

@jfeingold35
Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes issue wherein digital experience bundle pages could be fetched to the root folder by mistake if the correct subfolder didn't already exist.

What issues does this PR fix or reference?

@W-20967044@

Functionality Before

If you created a page in a digital experience bundle and fetched it via sf project retrieve start and thenchanged somethign about the mobile layout and fetched again, the mobile.json file would be created at the top-level for the page instead of nested in mobile/mobile.json.

Functionality After

The file is created in the correct subdirectory.

<insert gif and/or summary>

Comment thread test/convert/transformers/defaultMetadataTransformer.test.ts Outdated
Copy link
Copy Markdown
Member

@WillieRuemmele WillieRuemmele left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like the correct, and most minimal fix

@@ -92,7 +92,9 @@ const getContentSourceDestination = (
if (
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scope of this if block now is becoming somewhat unwieldy and requires a bit of effort expenditure for the reader.

This is probably a good candidate for partitioning into its own private function:

function shouldFlattenDigitalExperienceContentToViewFolder(source: SourcePath, dir: string): boolean {
  const isViewRootFile =
    source.slice(-12) === 'content.json' || source.slice(-10) === '_meta.json';
  const isMobileOrTabletFile =
    source.slice(-11) === 'mobile.json' || source.slice(-11) === 'tablet.json';
  const subfolderExists = fs.existsSync(dir) && fs.statSync(dir).isDirectory();
  return (
    isViewRootFile || (!subfolderExists && !isMobileOrTabletFile)
  );
}
// ...
if (shouldFlattenDigitalExperienceContentToViewFolder(source, dir)) {
  return join(mergeWith.content, basename(source));
}
//...

That said - the entire function is quite difficult to understand in its current state. We may want to just refactor the whole thing to save headaches for the next person who has to read this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this is prime territory for a refactoring. Given the tight timeframe for releasing the fix, I'd rather keep the changes minimal, and then just note this as a great area for us to go back to during a tech debt sprint.

@jfeingold35 jfeingold35 requested a review from a team as a code owner February 10, 2026 16:06
@iowillhoit
Copy link
Copy Markdown
Contributor

iowillhoit commented Feb 10, 2026

QA NOTES

SETUP

  • Create a scratch org
  • sf org open
  • Setup > Digital Experiences > Settings
  • Click Enable Digital Experiences
  • Click Save
  • Click OK (pop up)
  • Click Settings again
    • This will force reload the page to show all settings now that DE is enabled
  • Check Enable ExperienceBundle Metadata API
  • Click Save
  • Click Setup > Digital Experiences > All Sites
  • Click New
  • Select Build Your Own (LWR)
  • Click Get Started
  • Enter a Name
  • Click Create
  • Click Builder
  • Click the cog next to Home in the top nav
  • Click + New Page
  • Select Standard Page
  • Click + New Blank Page
  • Enter a Name
    • Demo1
  • Click Create

BEFORE CHANGES

Retrieve BEFORE changing view settings

  • Run sf project retrieve start
  • Look at sfdc_cms__view dir
    • Example: force-app/main/default/digitalExperiences/site/demo11/sfdc_cms__view/demo1
|____demo1
| |_____meta.json
| |____content.json
  • In Builder, click Desktop Icon in top right
  • Select Mobile
  • Select the bottom Column 1
  • In right nav, click Visibility
  • Disable Show Component on Mobile
  • Run sf project retrieve start again
  • 🔴 Notice that mobile.json is in top level of your page (bad)
|____demo1
| |_____meta.json
| |____content.json
| |____mobile.json

Retrieve AFTER changing view settings

  • Create a new page
  • Click the cog next to Home in the top nav
  • Click + New Page
  • Select Standard Page
  • Click + New Blank Page
  • Enter a Name
    • Demo2
  • Click Create
  • DON'T RETRIEVE
  • In Builder, click Desktop Icon in top right
  • Select Tablet (or Mobile)
  • Select the bottom Column 1
  • In right nav, click Visibility
  • Disable Show Component on Tablet
  • Run sf project retrieve start
  • 🟢 Notice that this time, the files are nested as expected
|____demo2
| |_____meta.json
| |____content.json
| |____tablet
| | |____tablet.json

AFTER CHANGES

  • Checkout this PR
  • yarn && yarn build
  • yarn link
  • cd to plugin-deploy-retrieve
  • Make sure it is up-to-date
  • Run yarn link @salesforce/source-deploy-retrieve
  • Run sf plugins link .
    • Confirm link with sf plugins

Retrieve BEFORE changing view settings

  • Create a new page
  • Click the cog next to Home in the top nav
  • Click + New Page
  • Select Standard Page
  • Click + New Blank Page
  • Enter a Name
    • Demo3
  • Click Create
  • Run sf project retrieve start
  • Look at sfdc_cms__view dir
    • Example: force-app/main/default/digitalExperiences/site/demo11/sfdc_cms__view/demo3
|____demo3
| |_____meta.json
| |____content.json
  • In Builder, click Desktop Icon in top right
  • Select Mobile
  • Select the bottom Column 1
  • In right nav, click Visibility
  • Disable Show Component on Mobile
  • Run sf project retrieve start again
  • 🟢 File in correct location mobile/mobile.json
|____demo3
| |_____meta.json
| |____content.json
| |____mobile
| | |____mobile.json

Retrieve AFTER changing view settings

  • Create a new page
  • Click the cog next to Home in the top nav
  • Click + New Page
  • Select Standard Page
  • Click + New Blank Page
  • Enter a Name
    • Demo4
  • Click Create
  • DON'T RETRIEVE
  • In Builder, click Desktop Icon in top right
  • Select Tablet (or Mobile)
  • Select the bottom Column 1
  • In right nav, click Visibility
  • Disable Show Component on Tablet
  • Run sf project retrieve start
  • 🟢 Files are (still) nested as expected
|____demo4
| |_____meta.json
| |____content.json
| |____tablet
| | |____tablet.json

🟢 BONUS (already in bad state)

  • Local org is already in a bad state
    • mobile.json and table.json at top level
|____demo5
| |_____meta.json
| |____content.json
| |____tablet.json
| |____mobile.json
  • Use new plugin-deploy-retrieve
  • Go to DE Builder
  • Select Mobile and/or Tablet
  • Select the bottom Column 1
  • In right nav, click Visibility
  • Toggle the visibility twice Show Component on Mobile
    • IMPORTANT NOTE: This triggers a change in the org so that source tracking will notice the change. Otherwise a standard sf project retrieve start will not pull changes. Alternatively, you can "force" a retrieve by specifying the DigitalExperience metadata type on retrieve, like so: sf project retrieve start -m DigitalExperience. I confirme this works.
  • Run sf project retrieve start again
Screenshot 2026-02-10 at 11 56 11 AM
  • 🟢 Top level mobile.json and tablet.json is removed
  • 🟢 Nested mobile/mobile.json and table/tablet.json is created
|____demo5
| |_____meta.json
| |____content.json
| |____tablet
| | |____tablet.json
| |____mobile
| | |____mobile.json

Copy link
Copy Markdown
Contributor

@iowillhoit iowillhoit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA notes added above

@iowillhoit iowillhoit requested a review from mshanemc February 10, 2026 18:05
@mshanemc mshanemc merged commit 9c0b900 into main Feb 10, 2026
47 checks passed
@mshanemc mshanemc deleted the d/W-20967044 branch February 10, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants