· ·

Upgrading to Content SDK 2.0: middleware.ts Is Now proxy.ts (and Other Surprises)

Alex Lentz

Title card: Upgrading to Content SDK 2.0: middleware.ts Is Now proxy.ts. Content SDK post on Sitecore Saga.

Content SDK 2.0 shipped last week (March 19th), and it’s the first major version since the SDK went stable. Major means breaking changes, and there are a few. None are hard, but some of them are sneaky – the kind that don’t fail the build and instead show up as “why is my redirect going to the wrong language?”

Here’s what I hit upgrading a Pages Router project from 1.5, roughly in the order I’d tackle them.

1. Next.js 16 and Node 24

The baseline moves to Next.js 16 (minimum ^16.0.0) and Node.js 24. Before you touch any Sitecore packages:

  • Update the Node version in your .nvmrc, CI images and xmcloud.build.json editing host config
  • Update Next.js and React together
  • Replace any images.domains in next.config.js with images.remotePatterns – domains is gone
// next.config.js
module.exports = {
  images: {
    // was: domains: ['edge.sitecorecloud.io']
    remotePatterns: [{ protocol: 'https', hostname: 'edge.sitecorecloud.io' }],
  },
};

2. middleware.ts is now proxy.ts

Next.js 16 renamed middleware to proxy, and the SDK followed. The good news: if you never customized the Sitecore middleware, this is mostly a find-and-replace.

Before (1.x), src/middleware.ts:

import { type NextRequest, type NextFetchEvent } from 'next/server';
import {
  defineMiddleware,
  MultisiteMiddleware,
  PersonalizeMiddleware,
  RedirectsMiddleware,
} from '@sitecore-content-sdk/nextjs/middleware';

export function middleware(req: NextRequest, ev: NextFetchEvent) {
  const multisite = new MultisiteMiddleware({ /* ... */ });
  const redirects = new RedirectsMiddleware({ /* ... */ });
  const personalize = new PersonalizeMiddleware({ /* ... */ });

  return defineMiddleware(multisite, redirects, personalize).exec(req, ev);
}

After (2.0), src/proxy.ts:

import { type NextRequest } from 'next/server';
import {
  defineProxy,
  MultisiteProxy,
  PersonalizeProxy,
  RedirectsProxy,
} from '@sitecore-content-sdk/nextjs/proxy';

export default function proxy(req: NextRequest) {
  const multisite = new MultisiteProxy({ /* same options as before */ });
  const redirects = new RedirectsProxy({ /* same options as before */ });
  const personalize = new PersonalizeProxy({ /* same options as before */ });

  return defineProxy(multisite, redirects, personalize).exec(req);
}

The summary: the file is renamed, the import path is /proxy, every *Middleware class is now *Proxy, the export is a default proxy function, and exec no longer takes the fetch event. Your config.matcher stays the same.

If you wrote custom middleware classes extending the SDK’s base classes, budget real time here and read the upgrade guide closely.

3. Cloud SDK is out, initContentSdk is in

The analytics and events functionality moved from the separate @sitecore-cloudsdk/* packages into new Content SDK packages: @sitecore-content-sdk/analytics-core, events and personalize. Initialization changes accordingly.

Before, in Bootstrap.tsx:

import { CloudSDK } from '@sitecore-cloudsdk/core/browser';
import '@sitecore-cloudsdk/events/browser';

CloudSDK({
  sitecoreEdgeUrl: config.api.edge.edgeUrl,
  sitecoreEdgeContextId: config.api.edge.clientContextId,
  siteName: page.siteName || config.defaultSite,
  enableBrowserCookie: true,
  cookieDomain: window.location.hostname.replace(/^www\./, ''),
})
  .addEvents()
  .initialize();

After:

import { initContentSdk } from '@sitecore-content-sdk/nextjs';
import { eventsPlugin } from '@sitecore-content-sdk/events';
import { analyticsBrowserAdapter, analyticsPlugin } from '@sitecore-content-sdk/analytics-core';

initContentSdk({
  config: {
    contextId: config.api.edge.clientContextId,
    edgeUrl: config.api.edge.edgeUrl,
    siteName: page.siteName || config.defaultSite,
  },
  plugins: [
    analyticsPlugin({
      options: {
        enableCookie: true,
        cookieDomain: window.location.hostname.replace(/^www\./, ''),
      },
      adapter: analyticsBrowserAdapter(),
    }),
    eventsPlugin(),
  ],
});

Then remove the @sitecore-cloudsdk/* packages from package.json. Search the codebase for @sitecore-cloudsdk – custom event tracking calls are easy to miss.

4. The sneaky ones

These don’t break the build. They change behavior.

Redirects and language. Redirects now default to the default locale unless “preserve language” is turned on for the rule in the Redirect Map. So /da/source -> /target used to land on /da/target and now lands on /target. If you have multilingual redirect maps, test them, and tick the language preservation checkbox where you need the old behavior.

Placeholder Suspense is off by default. disableSuspense now defaults to true for performance. If you were relying on Suspense boundaries around placeholders for loading states, turn it back on explicitly where you need it.

Edge hostname. SITECORE_EDGE_URL is no longer used. If you set a custom Edge hostname, move to SITECORE_EDGE_PLATFORM_HOSTNAME (NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME for the browser), and look at the new rewriteMediaUrls option if your media URLs need rewriting too.

Context and HOCs. SitecoreProvider now carries the componentMap and loadImportMap (which is required). The useComponentMap and useLoadImportMap HOCs are gone – use the useSitecore hook instead. withSitecore still works but is deprecated.

CLI config. In sitecore.cli.config.ts, the config property (pointing at your sitecore.config) is now required.

5. The new stuff worth adopting

Once you’re upgraded, a couple of things are worth turning on:

  • AGENTS.md, Skills.md and .agents/skills/. New scaffolds ship with agent skills for common tasks – component scaffolding, data fetching, troubleshooting editing, even an upgrade assistant. Copy them from a fresh create-content-sdk-app into your existing repo. If your team uses AI coding tools, this is a free quality upgrade.
  • @sitecore-content-sdk/search with the useSearch and useInfiniteSearch hooks, if you’re using SitecoreAI search.

My upgrade order

  1. Node 24, Next.js 16, remotePatterns
  2. Bump all @sitecore-content-sdk/* packages together, add the analytics packages, remove Cloud SDK
  3. middleware.ts to proxy.ts
  4. Bootstrap.tsx to initContentSdk
  5. Fix SitecoreProvider / HOC usage until it compiles
  6. Test redirects (multilingual especially), placeholders with loading states and editing in Page builder
  7. Copy over the agent skills

Big release, but a good one. And if you’re still on JSS: JSS 22.x is in maintenance mode, so this is the SDK to aim for.

Resources

Alex Lentz

Alex Lentz

Senior Solutions Architect at Americaneagle.com and two-time Sitecore Technology MVP. Building on Sitecore since 2013, mostly SitecoreAI and headless Next.js these days.

LinkedIn    GitHub

Keep reading