Lessons Learned When Trying to Move All the XM Cloud Furniture

Craig
Architect - Sitecore
  • Twitter
  • LinkedIn

First let me set the stage. We created an accelerator to build headless sites with an XM Cloud backend. We did this by creating a branch off the Sitecore JavaScript Rendering SDK. Over time we added functionality that we determined would be reusable across a large number of sites.

In the beginning we planned to use Vercel and we didn't know exactly what type of functionality the sites would require. Some might have blogs or news articles while others might not. Some would have Sitecore Search, while others might prefer Algolia or Coveo. To facilitate this, we created a number of packages so that clients could install only the packages they needed.

Initially we were running with Yarn. We also had a one-size-fits-all stylesheet which we would then modify for each client.

 

This all worked just fine for a while…

New functionality would be introduced, and we would attempt—where possible—to include functionality that was developed for a specific client back into the main accelerator repository. However, the changes started to come fast and furious.

 

Different Hosts for Different Folks and so on…

Some clients wanted to be hosted on Netlify whereas others preferred Vercel. To accommodate this, we changed the middleware that came from Sitecore’s example so that hosting could be controlled through environment variables. These changes were primarily made within the pages/api/editing files.

Another change we needed was to support multiple rendering hosts. This was done by modifying the xmcloud.build.json file. In fact, we needed four rendering hosts defined—one for each production site and one for each internal rendering host. To interpret variations in the configuration properties for these hosts, we made additional modifications to Sitecore’s example code.

 

Everybody’s got their own sense of style

Later, a particular client wanted a multi-site environment running from the same code base. All the components we developed would be enabled for both sites. The only difference was that each site required its own layouts and stylesheets so users could easily distinguish between the external-facing site and the internal-facing site.

To support this, we modified the Layout.tsx file along with some middleware from Sitecore’s example. The implementation looked something like the following:


export default function Layout({ layoutData, headLinks }: LayoutProps) {
  if (process.env.NEXT_PUBLIC_SITE_NAME === 'EXTERNAL') {
    return <EXTERNALLayout layoutData={layoutData} headLinks={headLinks} />
  }

  // Default to INTERNAL layout
  return <INTERNALLayout layoutData={layoutData} headLinks={headLinks} />
}

There were also many other minor changes spread throughout the repository.

Later, some clients requested that we adopt new functionality introduced in updates to the Sitecore example repository. One of these changes involved switching from Yarn to PNPM for package management.

 

Previously, our package.json looked something like this:


"workspaces": [
  "packages/*",
  "sites/*"
],
"scripts": {
  "build:mynewpackage1": "npm --workspace packages/mynewpackage1 run",
  "build:mynewpackage2": "npm --workspace packages/mynewpackage2 run"
}

This later changed to a much simpler structure:


"scripts": {
  "install-build": "pnpm install && pnpm build"
}

 

…and then it didn’t

However, this time it didn’t work. Yarn, as we discovered, had been much more flexible in how it handled references to internal packages. With PNPM being stricter, we initially believed we would need to remediate a large portion of our existing code.

In reality, the bigger issue was that our accelerator had diverged significantly from the original Sitecore example repository. This made it incredibly difficult to identify where updates needed to be applied. We also noticed that other smaller improvements made by Sitecore over time were missing from our implementation.

Ultimately, it became easier to start fresh from the latest example repository and carefully apply our custom commits to the new code base.

 

In Conclusion

The key lesson learned is that if you are working from a branch of one of Sitecore’s example repositories and want to keep it maintainable long term, you should avoid modifying the original files whenever possible. Treat these files as your foundational layer—similar to the Helix concept—and build your customizations around them rather than inside them.