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.
MVC to Headless Architecture Shift
Section titled “MVC to Headless Architecture Shift”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> );};Step 1: Choose Rendering Approach
Section titled “Step 1: Choose Rendering Approach”Two Primary Options (2026):
- 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 - 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
Step 2: Set Up Next.js Project
Section titled “Step 2: Set Up Next.js Project”Use Sitecore starter template:
npx create-next-app@latest --example https://github.com/Sitecore/jss/tree/dev/samples/nextjs my-xm-cloud-appcd my-xm-cloud-appnpm installConfigure Experience Edge connection:
.env.local:
SITECORE_API_KEY=your-edge-api-keySITECORE_API_HOST=https://xmc-your-tenant.sitecorecloud.ioGRAPH_QL_ENDPOINT=https://edge.sitecorecloud.io/api/graphql/v1JSS_APP_NAME=my-xm-cloud-appStep 3: Rebuild Components
Section titled “Step 3: Rebuild Components”Component Migration Process:
- Inventory MVC views — List all
.cshtmlfiles - Map to Next.js components — 1 view = 1 component
- 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
Step 4: Implement Routing
Section titled “Step 4: Implement Routing”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',});