
Local XM Cloud With Content-SDK
Learn how to stand up Sitecore XM Cloud locally with Windows Docker containers: initialize the environment, sync serialized items, configure the Content SDK rendering host, and wire Sitecore Pages for local editing—step-by-step for experienced Sitecore devs new to Docker.
Intro
I’ve been writing a multipart series (similar structure to the wildcard pages, custom sitemap, and server-side props posts on idksitecore.com) where each article opens with the “why”, dives into numbered build steps, drops targeted code blocks, and wraps with a “what’s next”. This entry follows the same recipe but focuses entirely on spinning up Sitecore XM Cloud locally with Docker, syncing serialized content, and wiring a Content SDK app to the local CD instance.
1. Prereqs & Mental Model
- Windows 11/Server 2022 host with Hyper‑V, WSL2, and Docker Desktop running in Windows containers.
- A valid license.xml on disk (
C:\License\license.xmlin examples). - Sitecore CLI 6.x installed (
dotnet tool restoreinside the repo handles this). - Access to your XM Cloud environment so you can serialize templates/content down to your machine.
2. Container Bootstrap (one‑time init)
What this does:
- Drops required host entries (
xmcloudcm.localhost,nextjs.xmc-starter-js.localhost). - Generates TLS certs via
mkcertand instructs you to run setx NODE_EXTRA_CA_CERTS <path-to-rootCA.pem>. - Seeds
.envwith image tags, SQL passwords, Auth0 config, media protection secret,JSS_EDITING_SECRET, andSITECORE_API_KEY_APP_STARTER. - Ensures
HOST_LICENSE_FOLDERpoints to the license directory.

3. Full Docker Workflow (daily usage)
Under the hood the script:
- Verifies the Sitecore license hasn’t expired.
- Pulls base CM/tools images (scr.sitecore.com/...:1-ltsc2022).
- Builds custom images defined in docker-compose.override.yml (Node base, CM overlay, Rendering host) and persists SQL/Solr data to
local-containers/docker/data. - Runs
docker compose up -dso the stack is:mssql,mssql-init,solr,solr-init,cm,rendering-nextjs,traefik. - Waits for Traefik to expose
cm-secure@docker. - Restores CLI tools, performs
dotnet sitecore cloud login,dotnet sitecore connect, populates Solr schemas, rebuilds indexes, pushes serialization, and imports the API key template.
NOTE: If docker compose build writes warnings to STDERR (e.g., Bake/credential helper messages), PowerShell’s $ErrorActionPreference = "Stop" may abort the script. Either patch the script to ignore those warnings or rerun the Docker commands manually (docker compose build && docker compose up -d) before re‑executing the CLI steps.
To tear everything down cleanly:

4. Items You Must Serialize From Your Remote XM Cloud
When you connect to the remote XM Cloud tenant, pull everything your local environment needs to mimic production. For a reference on the serialization, I posted some examples here.
Templates & Branches
/sitecore/templates/Foundation/*,/sitecore/templates/Feature/*,/sitecore/templates/Project/*
Rendering Definitions
/sitecore/layout/Renderings/Feature/...,/sitecore/layout/Renderings/Project/...
Placeholder Settings
/sitecore/layout/Placeholder Settings/...
Content Tree
/sitecore/content/<site>(all language versions that matter)
Media Items used locally
/sitecore/media library/Project/<site>
System Settings (*Most Important...otherwise you cannot connect Content SDK*)
/sitecore/system/Settings/Project/<site>/sitecore/system/Settings/Services/API Keys
PowerShell / automation assets
/sitecore/system/Modules/PowerShell/...
Example pull from remote cloud:
Push the same module into local CM after containers start:
5. Keys & Environment Variables to Track
Container .env essentials
Never commit real values—check .gitignore already excludes .env.
Content SDK (Next.js) .env.local
If you’re using graph-based configuration files, also point rendering service to http://cm internally.
6. Hooking Content SDK to Local XM Cloud
- Ensure the rendering container mounts your app (
../headapps/content-sdk-ssr:C:\appin docker-compose.override.yml). - Inside
headapps/content-sdk-ssrrun:
- Confirm
.env.localmatches the keys above. - Verify the XM Cloud CM API key exists at
/sitecore/system/Settings/Services/API Keys/content-sdk-test. If not, rerun:
- Use Traefik’s dashboard (
http://localhost:8079) to make surerendering-secure-nextjsroute isenabled. - Test the app at https://nextjs.xmc-starter-js.localhost. Use
docker compose logs -f rendering-nextjsfor troubleshooting.

7. Publishing? Not Locally.
XM Cloud local containers do not include Publishing Service and there’s no simulated CM ➜ CD promotion. Treat the environment as a developer sandbox: push serialized items, rebuild indexes, but don’t expect publish queues or workflow commands to function. For integrated testing you still push to your XM Cloud edge environment.
8. Getting Page Designer to Talk to Local CM
Sitecore Pages caches the target CM URL in browser local storage. Without overriding it, Pages keeps pointing to the hosted environment and refuses to load the local rendering host.
Steps (credit to the Fishtank article):
- Open Pages (https://pages.sitecorecloud.io) and log in.
- In DevTools → Application → Local Storage → https://pages.sitecorecloud.io, add:
- Reload Pages; when you open a page, it proxies requests to your local CM and the Traefik-secured rendering host.
9. Summary Checklist
init.ps1(once per machine) to generate.env, certs, hosts, and secrets.up.ps1(each session) to pull/build/run containers + run CLI chores.- Serialize templates/content/API keys from cloud (
ser pull) and push into local (ser push). - Keep
.envkeys in sync between containers and the Content SDK app. - Remember: no publishing pipeline locally—serialization is your deployment story.
- Set Pages’ local storage override so Page Designer can target https://xmcloudcm.localhost/.
Follow that flow and anyone with Sitecore/XM Cloud experience—but minimal Docker knowledge—can clone the repo, run two scripts, sync items, and get the Content SDK rendering locally with confidence.