Insights

Get Rid of Development Environment CORS Errors in Experience Editor When Using a Docker Next.js Rendering Host

Ensuring web resources load properly across all environments is crucial for developers and users, preventing broken functionality and appearance

State of the Sitecore Docker and Next.js Starter Kits

At the time of writing these lines, whether you create a project from the XM starter kit or the XM Cloud starter kit, both are affected by the same issue: CORS errors in the browser console in the Experience Editor. This only occurs on development environments on Docker. This does not happen on hosted XM Cloud environments. This could also happen on hosted XM environments.

In this blog post, we will cover the Docker development environment scenario.

How Do I Know if I Have CORS Errors?

In Experience Editor, open the browser developer tools in the console tab. If you see CORS errors similar to those, you are affected by this issue:

Why Are There CORS Errors?

When running the Experience Editor, the page domain is the Content Manager (CM) domain: https://xmcloudcm.localhost/

However, the HTML in the DOM of the Experience Explorer is coming from the rendering host. The Experience Editor asks the rendering host to return the server-side rendered (SSR) version of the page in edit mode: https://${RENDERING_HOST}/api/editing/render

The HTML page returned by the rendering host contains many absolute URLs with the rendering host domain as the rendering container PUBLIC_URL environment variable is by default set to "https://${RENDERING_HOST}". For the XM Cloud starter kit, it translates to https://www.sxastarter.localhost.

As the Experience Editor HTTP response does not specify any Access-Control HTTP headers, the requests to the absolute rendering host URLs are blocked by the browser CORS protections.

How to Get Rid of the CORS Errors?

This solution consists of adding the required HTTP headers to all the responses of the rendering host Next.js application. One way to achieve that is by configuring the Traefik HTTP proxy to do it.

  1. Edit your project docker-compose.override.yml file.
  2. Locate your rendering service.
  3. Locate the service labels. You will usually find these:

     labels:
       - "traefik.enable=true"
       - "traefik.http.routers.rendering-secure.entrypoints=websecure"
       - "traefik.http.routers.rendering-secure.rule=Host(`${RENDERING_HOST}`)"
       - "traefik.http.routers.rendering-secure.tls=true"
    

    Yours may be slightly different.

  4. Add the following labels just after your last one.

     # BEGIN CUSTOMIZATION - Add CORS headers to fix CORS issues in Experience Editor with Next.js 12.2 and newer
     - "traefik.http.middlewares.rendering-headers.headers.accesscontrolallowmethods=GET,POST,OPTIONS"
     - "traefik.http.middlewares.rendering-headers.headers.accesscontrolalloworiginlist=https://${CM_HOST}"
     - "traefik.http.routers.rendering-secure.middlewares=rendering-headers"
     # END CUSTOMIZATION
    
  5. You will end up with the following configuration:

     labels:
       - "traefik.enable=true"
       - "traefik.http.routers.rendering-secure.entrypoints=websecure"
       - "traefik.http.routers.rendering-secure.rule=Host(`${RENDERING_HOST}`)"
       - "traefik.http.routers.rendering-secure.tls=true"
       # BEGIN CUSTOMIZATION - Add CORS headers to fix CORS issues in Experience Editor with Next.js 12.2 and newer
       - "traefik.http.middlewares.rendering-headers.headers.accesscontrolallowmethods=GET,POST,OPTIONS"
       - "traefik.http.middlewares.rendering-headers.headers.accesscontrolalloworiginlist=https://${CM_HOST}"
       - "traefik.http.routers.rendering-secure.middlewares=rendering-headers"
       # END CUSTOMIZATION
    

    These labels are used by the Traefik container to:

    1. Create a new rendering-headers Traefik middleware.
    2. Define 2 HTTP headers on this middleware:
      1. Access-Control-Allow-Methods: GET,POST,OPTIONS
      2. Access-Control-Allow-Origin: https://${CM_HOST}
        1. The CM_HOST variable is usually defined in the main .env file.
        2. On an XM Cloud project, its value is most of the time xmcloudcm.localhost. Thus, the allowed origin becomes https://xmcloudcm.localhost.
        3. On an XM/XP project, its value is usually cm.<your_project_name>.localhost. Thus, the allowed origin becomes https://cm.<your_project_name>.localhost.
    3. Attach this new Traefik middleware to the existing rendering-secure Traefik router.
  6. Save the file.
  7. Assuming your solution is already initialized, and your containers are already running: In a PowerShell terminal running as administrator in your solution folder, restart the rendering container by running the docker compose up -d command.
    1. This will compare the running containers with the Docker compose configuration, and recreate the containers with a modified configuration.
  8. Wait for the containers to be ready.
  9. Monitor your rendering container logs to know when it has compiled the next.js project and it is ready to receive requests.
  10. Access the Experience Editor and enjoy having no CORS errors anymore.

Wrapping Up on CORS Errors

I hope you better understand the cause of Experience Editor CORS errors and this solution worked for your project. Other solutions might include configuring Access-Control HTTP headers directly in the Next.js application next.config.js file or as a Next.js middleware.

Happy Sitecoring!



Meet Jeff L'Heureux

Director of Technology

🧗‍♂️🏔️ 🍺

Jean-François (Jeff) L'Heureux is an experienced leader in Sitecore and Coveo technologies, having worked in both organizations. He is a three-times Sitecore Technology MVP and three-time Coveo MVP. He has 16 years of software development experience, including ten years of Sitecore experience. He specializes in front-end, and he has experience in technologies like Next.js, React, Vercel, Netlify, Docker, Coveo Cloud, Coveo for Sitecore, Sitecore XP/XM, and the latest Sitecore technologies, including XM Cloud, JSS, CDP, Personalize, OrderCloud, Discover, Send, Search, and Content Hub ONE. Outside work, he can be found outside rock climbing, mountain biking, hiking, snowshoeing, or cross-country skiing.

Connect with Jeff