Content SDK 1.1 shipped last week (September 23rd), and since 1.0 only went stable in July, this is the first “real” upgrade a lot of XM Cloud teams are going to do on the new SDK.
The release notes cover a lot – Design Library enablers, display name routing fixes, cache busting changes – but there are three things I’d actually look at before bumping the version on a client project. One of them can quietly break your editing host if you’re not on a standard setup.
1. Editing render no longer redirects – it calls itself
This is the one to read twice.
In 1.0, when Pages asked your editing host to render a page, the editing render middleware handed back a temporary redirect to the page route. In 1.1 that’s gone. The middleware now makes an internal server request to your own Next.js app to fetch the page data. Fewer round trips, faster editing, all good – as long as the app can actually reach itself.
How it figures out where “itself” is:
sitecoreInternalEditingHostUrlinsitecore.config.ts, if you set it- The
SITECORE_INTERNAL_EDITING_HOST_URLenvironment variable - If neither is set:
http://localhost:3000when running in XM Cloud, or the incoming request’s host header on Vercel / Netlify
For the default XM Cloud editing host and a vanilla Vercel deployment, you don’t need to do anything. Where I’d expect trouble:
- Your editing host runs on a port other than 3000
- It’s behind a reverse proxy or App Gateway where the public host name doesn’t resolve from inside the container
- You’ve got a custom base path
If your editing host starts throwing errors in Pages after the upgrade, this is the first place to look. Set it explicitly:
// sitecore.config.ts
import { defineConfig } from '@sitecore-content-sdk/nextjs/config';
export default defineConfig({
// Where the editing host can reach itself from the server side
sitecoreInternalEditingHostUrl: process.env.SITECORE_INTERNAL_EDITING_HOST_URL,
});
# .env (editing host only)
SITECORE_INTERNAL_EDITING_HOST_URL=http://localhost:8080
I like keeping it env-driven even though the config property would win on its own. That way the same code works on the XM Cloud editing host, a Docker container and a dev box without a code change.
2. ESLint 9 and the flat config
The SDK and the starter moved from ESLint 8 to ESLint 9, which means .eslintrc is out and eslint.config.mjs is in. If you scaffolded from the 1.0 starter, your lint setup is going to fail the first time you npm install the new versions.
The new template config is pretty readable. The shape looks like this:
// eslint.config.mjs (trimmed)
import { defineConfig } from 'eslint/config';
import js from '@eslint/js';
import * as nextEslintPlugin from '@next/eslint-plugin-next';
import tsParser from '@typescript-eslint/parser';
const nextPlugin = nextEslintPlugin.default ?? nextEslintPlugin;
export default defineConfig([
{ ignores: ['node_modules/**', '.next/**', 'dist/**'] },
js.configs.recommended,
{ plugins: { '@next/next': nextPlugin } },
{
files: ['**/*.{js,jsx,ts,tsx}'],
languageOptions: { parser: tsParser },
rules: {
...(nextPlugin.configs?.recommended?.rules ?? {}),
'@next/next/no-img-element': 'off',
},
},
]);
My advice: don’t hand-convert your old .eslintrc. Copy the template’s eslint.config.mjs from a fresh npx create-content-sdk-app, then port over only the custom rules you actually care about. Most of us have rules in there that nobody remembers adding.
3. Cursor rules in the starter
This is the fun one. The Next.js starter now ships with a .cursor/rules folder:
.cursor/rules/
general.mdc
javascript.mdc
project-setup.mdc
sitecore.mdc
Each .mdc file has frontmatter that tells Cursor when to pull it in – sitecore.mdc for example is scoped with globs to src/components/**, src/lib/** and sitecore.config.ts. So when you ask Cursor to build a component, it already knows to use the Sitecore field components, to handle empty fields, to follow the naming conventions and so on.
I’ve been leaning on AI-assisted development a lot this year, and the biggest quality jump always comes from giving the model your team’s conventions, not the framework’s. The shipped rules are a solid base. Add your own on top:
---
description: Team conventions for Sitecore components
alwaysApply: false
globs:
- 'src/components/**'
---
# Team component conventions
- Every rendering gets a matching `*.stories.tsx` file with an empty-fields story
- Datasource fields are typed with the Content SDK field types, never `any`
- Never hard-code copy. If an author might want to change it, it's a field or a dictionary entry
- Images always go through the Sitecore `Image` component so editing keeps working
- Keep components presentational. Data fetching lives in `getComponentServerProps`
Drop that in .cursor/rules/team-components.mdc and commit it. Now every developer on the team (and every AI assistant they use) works from the same playbook.
Should you upgrade?
Yes, but read the 1.1 upgrade guide first and test editing specifically – not just the public site. Here’s the checklist I’m using:
- Bump the
@sitecore-content-sdk/*packages together - Replace
.eslintrcwith the new flat config - Verify editing in Pages on a non-prod environment
- If editing breaks, set
SITECORE_INTERNAL_EDITING_HOST_URL - Grab the
.cursor/rulesfolder from a fresh starter, even if you’re not using Cursor today – they double as decent onboarding docs
Resources
- Content SDK 1.1 changelog: https://developers.sitecore.com/changelog/sitecoreai/23092025/content-sdk-1.1-released-with-design-library-enablers%2C-cursor-rules%2C-optimized-preview-and-editing-modes%2C-and-more.-
- Content SDK on GitHub: https://github.com/Sitecore/content-sdk
- Upgrade guide (1.0 to 1.1): https://doc.sitecore.com/xmc/en/developers/content-sdk/upgrade-content-sdk-1-0-0-next-js-apps-to-version-1-1-0.html




