Skip to content
Sitecore

XP to XM Cloud Phase 4: Frontend Rebuild

This is 60-70% of total migration effort. Every MVC view must be rewritten as a Next.js component. This phase typically takes 12-24 weeks.

Old (XP MVC Razor):

@model MyProject.Models.ArticlePage
<div class="article">
<h1>@Model.Item["Title"]</h1>
<div class="body">
@Html.Sitecore().Field("Body", Model.Item)
</div>
<div class="related">
@Html.Sitecore().Placeholder("related-articles")
</div>
</div>

New (XM Cloud Next.js + Content SDK):

import { Text, RichText, Field } from '@sitecore-content-sdk/nextjs';
import { ComponentRendering, ComponentParams } from '@sitecore-content-sdk/nextjs';
type ArticleFields = {
title: Field<string>;
body: Field<string>;
};
type ArticleProps = {
rendering: ComponentRendering;
params: ComponentParams;
fields: ArticleFields;
};
export const Article = (props: ArticleProps): JSX.Element => {
return (
<div className="article">
<h1>
<Text field={props.fields.title} />
</h1>
<div className="body">
<RichText field={props.fields.body} />
</div>
</div>
);
};

Two Primary Options (2026):

  1. Content SDK (Recommended) — The modern replacement for JSS. Lighter, TypeScript-first, supports App Router (GA since Content SDK v1.3.1, Dec 2025). Package: @sitecore-content-sdk/nextjs
  2. JSS SDK (Legacy, still supported) — The previous-generation SDK. Package: @sitecore-jss/sitecore-jss-nextjs. Still receives updates but Content SDK is the strategic direction.

Both approaches work with Headless SXA — Sitecore’s component library for rapid development with pre-built components and drag-and-drop layout in Pages editor. SXA is not a separate rendering approach; it layers on top of Content SDK or JSS.

Decision Matrix:

  • Use Content SDK when: Starting new XM Cloud projects (recommended default), want App Router support, want modern React patterns
  • Use JSS when: Migrating an existing JSS app gradually, need Pages Router compatibility

Use Sitecore starter template:

Terminal window
npx create-next-app@latest --example https://github.com/Sitecore/jss/tree/dev/samples/nextjs my-xm-cloud-app
cd my-xm-cloud-app
npm install

Configure Experience Edge connection:

.env.local:

SITECORE_API_KEY=your-edge-api-key
SITECORE_API_HOST=https://xmc-your-tenant.sitecorecloud.io
GRAPH_QL_ENDPOINT=https://edge.sitecorecloud.io/api/graphql/v1
JSS_APP_NAME=my-xm-cloud-app

Component Migration Process:

  1. Inventory MVC views — List all .cshtml files
  2. Map to Next.js components — 1 view = 1 component
  3. Estimate effort — 1-2 days per complex component, 0.5 day per simple component

Example Effort Calculation:

  • 50 components total
  • 20 simple (0.5 day each) = 10 dev-days
  • 20 medium (1 day each) = 20 dev-days
  • 10 complex (2 days each) = 20 dev-days
  • Total: 50 dev-days = 10 weeks for 1 frontend developer

XM Cloud uses Experience Edge for routing.

Configure catch-all route ([[...path]].tsx):

import { SitecorePageProps } from 'lib/page-props';
import { sitecorePagePropsFactory } from 'lib/page-props-factory';
import { componentBuilder } from 'temp/componentBuilder';
import { SitecoreContext, ComponentPropsContext } from '@sitecore-jss/sitecore-jss-nextjs';
import Layout from 'src/Layout';
const SitecorePage = ({ layoutData, componentProps }: SitecorePageProps): JSX.Element => {
return (
<ComponentPropsContext value={componentProps}>
<SitecoreContext componentFactory={componentBuilder.getComponentFactory()} layoutData={layoutData}>
<Layout layoutData={layoutData} />
</SitecoreContext>
</ComponentPropsContext>
);
};
export async function getStaticProps(context) {
const props = await sitecorePagePropsFactory.create(context);
return {
props,
revalidate: 5, // ISR: revalidate every 5 seconds
};
}
export async function getStaticPaths() {
return {
paths: [], // Pre-rendered at build time: none
fallback: 'blocking', // Server-render on first request
};
}
export default SitecorePage;

Step 5: Handle Personalization (if needed)

Section titled “Step 5: Handle Personalization (if needed)”

Embedded Personalization (Included in XM Cloud): Component-level variants selected in Pages editor.

Advanced Personalization (Requires Sitecore Personalize + CDP): Client-side integration with real-time segments.

Example (Personalize integration via Cloud SDK):

import { personalize } from '@sitecore-cloudsdk/personalize/browser';
// Initialize Cloud SDK first (typically in _app.tsx or layout)
// Then call personalize in your component:
const response = await personalize({
channel: 'WEB',
currency: 'USD',
friendlyId: 'hero-experience',
});