Setup XM Cloud Multi-site on Netlify
Tags: sitecore, xmcloud, netlify
Published: 2024-04-17 17:06:59

We had some interesting struggles getting XM Cloud multi-site to work on Netlify. We would like to make it easier for other people to get this setup and running. Many thanks to [Richard Seal](https://www.linkedin.com/in/richardseal/) for his help  getting this all setup correctly. 

### A couple of notes before we start

- This solution will pertain to a single Netlify environment that will be hosting several different websites at once.
- Some of the solutions recommended below are known issues with Sitecore, and may not be steps you need to take in the future. At the time of writing this the application was on version 21.6.4 of [Sitecore JSS](https://github.com/Sitecore/jss). I will try to remember to indicate this, but I make no promises ahead of time.
- Several images will contain information that is blurred out to maintain the confidentiality of the environment. Many pixels were harmed in the creation of this post.
- There might be some sarcasm along the way. 

## Setup and The Problem

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqcytiyfk8e60xv8vr11.png)

For this implementation the customer was looking to simplify the deployment of their smaller sites. So we setup several sites within one XM Cloud tenant.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ppmb6wr5l0liojt6skz.png)

Each of those had the site grouping setup with the appropriate Hostname, sitename, Predefined application rendering host, etc.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/posdvs8ovufnmcmfm6am.png)

SXA Site Manager was even showing green lights across the board. 

The problem that manifested is that when we would attempt to load any of the sites, we would get a continual reload of the page. Several times a second it would send a new request to the server. This didn't seem like an ideal solution.

If you page is doing this, open the developer tools in the browser. You will likely see it is attempting to get resources from the wrong website.


---
## The Solution
### Netlify Setup
So everything above is setup how it is supposed to be setup. Let's go to Netlify setup and pull out some juicy details.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6fqg27qg8znlplwiqoa.png)

- **FETCH_WITH** : Usually going to be "GraphQL". We are not sure if this is really needed, but it does not hurt
- **PUBLIC_URL** : This should be set to nothing. The field should be empty. See I am not lying 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylf3ttz9terd5t8z31eu.png)
- **SITECORE_EDGE_CONTEXT_ID** : This is the context id you get from the [Sitecore deploy site](https://deploy.sitecorecloud.io/).
- **SITECORE_SITE_NAME** : This should correspond to the name of one of the sites above. Just one, no more. The rest is taken care of by the Nextjs multi-site plugin.

### Code Changes
With that, Netlify should be setup. But wait, there's more, this is also what might be fixed in the version of the code you are using. So this may not be applicable.

We need to create an _.env_ file with no values set. So open up the directory with your Nextjs application. (e.g. _/src/'project name'/.env_). I chose to copy the _starter.env_ file because it had all the fields we needed to set. All the fields should be cleared though. In essence what happening is we are creating some default values for the websites in Netlify, and then using the Netlify environment variables to overwrite these defaults.  

Here is a sample of that _.env_ file in case you had deleted it:
```
# For development purposes, note Next.js supports a .env.local
# file, which is already configured to be git ignored.
# Read more about Next.js support of environment variables here:
# https://nextjs.org/docs/basic-features/environment-variables

# The public URL to use for absolute URLs, which are required when
# the Next.js app is run within Sitecore editors.
# This should match the `serverSideRenderingEngineApplicationUrl`
# in your Sitecore configuration (see \sitecore\config\sxastarter.config).
# Be sure to update these values accordingly as your public endpoint changes.
# See https://jss.sitecore.com/docs/fundamentals/services/view-engine
PUBLIC_URL=

# To secure the Sitecore editor endpoint exposed by your Next.js app
# (`/api/editing/render` by default), a secret token is used. This (client-side)
# value must match your server-side value (see \sitecore\config\sxastarter.config).
# We recommend an alphanumeric value of at least 16 characters.
JSS_EDITING_SECRET=

# Your Sitecore API key is needed to build the app. Typically, the API key is
# defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
# when building locally (if you've never run `jss setup`), or when building in a
# higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_KEY=

# Your Sitecore API hostname is needed to build the app. Typically, the API host is
# defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
# not exist when building locally (if you've never run `jss setup`), or when building
# in a higher environment (since `scjssconfig.json` is ignored from source control).
# In this case, use this environment variable to provide the value at build time.
SITECORE_API_HOST=

# Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
# For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
# the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
GRAPH_QL_ENDPOINT=

# Your Sitecore app name (also used as the default site name). Overrides 'config.appName' defined in a package.json
# Get this from the site > Settings > Developer settings , eg: 'brandstudio'
SITECORE_SITE_NAME=

# Your default app language.
DEFAULT_LANGUAGE=

# How many times should GraphQL Layout, Dictionary and ErrorPages services retry a fetch when endpoint rate limit is reached
GRAPH_QL_SERVICE_RETRIES=

# The way in which layout and dictionary data is fetched from Sitecore
FETCH_WITH=

# Indicates whether SSG `getStaticPaths` pre-render any pages
# Set the environment variable DISABLE_SSG_FETCH=true
# to enable full ISR (Incremental Static Regeneration) flow
DISABLE_SSG_FETCH=

# Sitecore JSS npm packages utilize the debug module for debug logging.
# https://www.npmjs.com/package/debug
# Set the DEBUG environment variable to 'sitecore-jss:*' to see all logs:
#DEBUG=sitecore-jss:*
# Or be selective and show for example only layout service logs:
#DEBUG=sitecore-jss:layout
# Or everything BUT layout service logs:
DEBUG=

# An optional Sitecore Personalize scope identifier.
# This can be used to isolate personalization data when multiple XM Cloud Environments share a Personalize tenant.
# This should match the PAGES_PERSONALIZE_SCOPE environment variable for your connected XM Cloud Environment.
NEXT_PUBLIC_PERSONALIZE_SCOPE=

# Timeout (ms) for Sitecore CDP requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT=

# Timeout (ms) for Sitecore Experience Edge requests to respond within. Default is 400.
PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT=

#Get this context from the 
SITECORE_EDGE_CONTEXT_ID=
```

That is just about it. You will likely need to do a build and deploy on Netlify to pick everything up. Publishing might not be a bad idea either.

I welcome your comments or questions. Together we make more time to do the fun things around implementations.