Troubleshooting Sitecore AI Design Studio
January 22, 2026 • Nona Dzhurkova • 6 min read

Troubleshooting Sitecore AI Design Studio

Right after the Symposium, when SitecoreAI was live, we first tried to test Design Studio. But when we opened it, a lot of errors popped up, starting with "mock data cannot be generated", blocked requests, and inconsistency. Our project was migrated to Content SDK 1.1 and we expected everything to work smoothly. This post describes what went wrong, what we learned, and what finally fixed it.

Vercel protection and query string problems

Some requests to /api/editing/config or /api/editing/render failed with 401 errors, mostly in Design Library mode.

When Vercel deployment protection query parameters were used, Design Library sometimes added Sitecore parameters incorrectly, using ? instead of &. Because of this, the secret was not passed correctly.

This behavior was confirmed during the support investigation and later mitigated.

Rendering host must be fully configured

Design Studio worked inconsistently and some checks on the frontend did not behave correctly. We got errors that we should migrate to Content SDK, which was a strange message as we already migrated to Content SDK 1.1.

There were multiple rendering hosts configured, but the "Default" rendering host was empty. Sitecore expects all rendering hosts to be filled in.

To fix it - Fill in all fields of the Default rendering host item.

Design Studio blocked by CSP issues

Note: This was by far the most time-consuming problem to solve, taking several weeks of investigation and multiple support mails.

When opening Design Studio or Design Library, the page did not load. In the browser console we saw errors saying the page was blocked because of Content Security Policy and frame-ancestors.

We already had our own CSP middleware. For /api/editing/* routes, CSP was disabled on purpose, to avoid problems with Sitecore editors.

Even with CSP disabled for those routes, responses from /api/editing/render still contained this header:

frame-ancestors 'self' https://pages.sitecorecloud.io

Because of this, requests coming from other Sitecore editor domains were blocked, especially when running behind Vercel.

After checking headers many times, it became clear that CSP was being set or overwritten later in the request flow. Most likely this was done by Sitecore editing middleware.

Because of that:

  • our CSP rules were ignored
  • only pages.sitecorecloud.io was allowed
  • Design Library and xmapps editor hosts were blocked

This was confusing at first, because the CSP did not come from our middleware.

Sitecore support propose following solutions

  • Upgrade the Content SDK to version 1.3.0.
  • Add an environment variable named EDITING_ALLOWED_ORIGINS with value = “*“ or “https://designlibrary.sitecorecloud.io”

We added in the deploy app the environment variable - we tested with both values, but the result stays the same. We cannot afford to migrate to Content SDK 1.3 at this stage.

After several attempts and support discussions, the real fix was done in code.

We updated our own CSP helper - in the function applyEditingRouteCspHeaders(), we intercepted res.setHeader and forced only the frame-ancestors part of Content-Security-Policy.

This change was applied only for /api/editing/* routes.

Final frame-ancestors value:

  • 'self'
  • https://pages.sitecorecloud.io
  • https://designlibrary.sitecorecloud.io
  • https://xmapps.sitecorecloud.io
  • https://*.sitecorecloud.io

We did not replace the full CSP. We only made sure that the final response always contains the correct frame-ancestors, even if some other code sets CSP later.

Here are the helper functions we implemented in our CSP utils:

export function getSitecoreEditingFrameAncestors(): string[] {
  return [
    "'self'",
    'https://pages.sitecorecloud.io',
    'https://designlibrary.sitecorecloud.io',
    'https://xmapps.sitecorecloud.io',
    'https://*.sitecorecloud.io',
  ];
}

export function buildFrameAncestorsCspValue(frameAncestors: string[]): string {
  return `frame-ancestors ${frameAncestors.join(' ')}`;
}

/**
 * Apply CSP/XFO headers for Next.js API routes under /api/editing/*
 * - Sets Content-Security-Policy (frame-ancestors ...)
 * - Ensures X-Frame-Options doesn't block framing
 */
export function applyEditingRouteCspHeaders(
  req: { url?: string | null },
  res: {
    setHeader: (name: string, value: any) => void;
    removeHeader?: (name: string) => void;
  }
): void {
  const url = req.url || '';
  const pathname = url.split('?')[0];

  if (!pathname.startsWith('/api/editing')) return;

  const desiredFrameAncestors = buildFrameAncestorsCspValue(getSitecoreEditingFrameAncestors());

  const ensureFrameAncestors = (csp: string): string => {
    const parts = csp
      .split(';')
      .map((p) => p.trim())
      .filter(Boolean);

    let replaced = false;
    const updated = parts.map((p) => {
      if (p.toLowerCase().startsWith('frame-ancestors ')) {
        replaced = true;
        return desiredFrameAncestors;
      }
      return p;
    });

    if (!replaced) updated.push(desiredFrameAncestors);

    return updated.join('; ');
  };

  // Patch setHeader so that if downstream code overwrites CSP, we still enforce our frame-ancestors.
  const originalSetHeader = res.setHeader.bind(res);
  res.setHeader = (name: string, value: any) => {
    if (name.toLowerCase() === 'content-security-policy') {
      const current = Array.isArray(value) ? value.join('; ') : String(value ?? '');
      const next = ensureFrameAncestors(current);
      return originalSetHeader(name, next);
    }
    return originalSetHeader(name, value);
  };

  // Set it now as well (in case no downstream CSP is set)
  originalSetHeader('Content-Security-Policy', desiredFrameAncestors);

  // Do not send X-Frame-Options: DENY/SAMEORIGIN for editor endpoints
  res.removeHeader?.('X-Frame-Options');
}

And here's how we updated the api/editing/render file to use this CSP helper:

import type { NextApiRequest, NextApiResponse } from 'next';

import { EditingRenderMiddleware } from '@sitecore-content-sdk/nextjs/editing';
import { applyEditingRouteCspHeaders } from '@/lib/utils/cspUtils';

/**
 * This Next.js API route is used to handle GET requests from Sitecore Editor.
 * This route should match the `serverSideRenderingEngineEndpointUrl` in your Sitecore configuration,
 * which is set to "http:///api/editing/render" by default (see the settings item under /sitecore/content//Settings/Site Grouping).
 *
 * The `EditingRenderMiddleware` will
 *  1. Extract data about the route we need to render from the Sitecore Editor GET request
 *  2. Enable Next.js Preview Mode, passing the route data as preview data
 *  3. Redirect the request to the route, passing along the Preview Mode cookies.
 *     This allows retrieval of the editing data in preview context (via an `EditingDataService`) - see `SitecorePagePropsFactory`
 *  4. The redirected request will render the page with editing markup in place
 */

export const config = {
  api: {
    bodyParser: {
      sizeLimit: '2mb',
    },
    responseLimit: false,
  },
};

// Wire up the EditingRenderMiddleware handler
const editingHandler = new EditingRenderMiddleware().getHandler();

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  applyEditingRouteCspHeaders(req, res);
  return editingHandler(req as any, res);
}

What's Next

Finally, we have our Design Studio working! Our solution is implemented with a shared site and multiple sites which reuse variants and allowed components from the shared site. We still have a few things to investigate:

  • Variants visibility: The variants are shown only for the Shared Site
  • Branding: The branding works amazingly well! When switching between sites for the same component, we can see the colors are updated. Really impressed!
  • Search components: We saw some errors on Search components which we need to review. However, our Search components for Related items are working amazingly well
  • GraphQL components: Most of the GraphQL components do not show any data - this may be a limitation of our implementation so we will review further
  • Page template components: The components reading from page template are also not showing any information
  • Mock data: Still isn't clear where all mock data is created

But most of the datasource components work very well. We may even change the datasource to another one to see how they will appear. I noticed that by default, Design Studio opens the Site Home page/Data folder from where you can select another datasource.

Featured Blogs