Migrate Content Slots from SFRA to Storefront Next
In Storefront Next, React components replace ISML templates. If you’re migrating from Salesforce Storefront Reference Architecture (SFRA) and rely on content slots, use this workaround until the planned Embedded Content feature becomes available.
Content Slot Workaround Overview
This workaround lets you manage reusable HTML content, such as shipping policies, disclaimers, or promotional blocks, in Page Designer and embed it across your storefront. It provides:
A “Content Slot Page” page type with a single content region.
A “Markup Content” component type with a markup attribute for HTML.
A React component that renders the markup using the HtmlFragment component.
Create the markup content in src/components/markup-content/index.tsx.
1import { Component } from "@/lib/decorators/component";2import { AttributeDefinition } from "@/lib/decorators/attribute-definition";3import { RegionDefinition } from "@/lib/decorators/region-definition";4import HtmlFragment from "@/components/html-fragment";5import type { ComponentType } from "@/components/region";67@Component("markupContent", {8 name: "Markup Content",9 description: "Displays HTML markup content - use for reusable content blocks",10})11@RegionDefinition([])12export class MarkupContentMetadata {13 @AttributeDefinition({ type: "markup", name: "Markup" })14 markup?: string;15}1617interface MarkupContentProps {18 markup?: string;19 component?: ComponentType;20}2122export default function MarkupContent({ markup, component }: MarkupContentProps) {23 const content = markup || (component?.data?.markup as string) || "";2425 if (!content) return null;2627 return <HtmlFragment content={content} />;28}
Step 2: Create the Content Slot Page Type JSON
Create the content slot page. Add the contentSlotPage.json file in cartridges/app_storefrontnext_base/cartridge/experience/pages/ and add this content.
Content slot pages need a preview route to be editable in Page Designer’s design mode. Create the _app.content-slot.tsx file in src/routes/_app.content-slot.tsx and add this content.
1import { Region } from "@/components/region";2import { fetchPageWithComponentData } from "@/lib/util/pageLoader";3import type { LoaderFunctionArgs } from "react-router";45export function loader(args: LoaderFunctionArgs) {6 return {7 // Replace {content-id} with the ID of the page you create in Page Designer8 page: fetchPageWithComponentData(args, { pageId: "{content-id}" }),9 };10}1112export default function ContentSlotPreviewPage({ loaderData }) {13 return (14 <div className="max-w-7xl mx-auto px-4 py-8">15 <Region page={loaderData.page} regionId="content" />16 </div>17 );18}
Step 4: Generate and Deploy Metadata
Use these commands to generate and deploy the metadata.
To be able to bind content assets to components in Page Designer, turn on a feature switch. In Administration > Global Preferences > Feature Switches, turn on Enable Page Designer Data Binding.
Important
Create a content slot page in Merchant Tools > Content > Page Designer > New Page.
Select Content Slot Page as the page type.
Add Markup Content components to the “content” region.
Configure markup by entering HTML directly or by using data binding to bind to Content Assets.
Assign a page ID (for example, shipping-policy or legal-disclaimer). You reference this ID when fetching the page.
Populate the Content
You can populate content in two ways.
Option 1: Direct HTML entry
Enter HTML directly in the Markup field of a Markup Content component. This approach is best for content that is specific to your Storefront Next storefront.
Option 2: Data binding to content assets
Bind the Markup field to a content asset’s HTML attribute. This approach is best for content that must be shared across multiple storefront technologies (SFRA and Storefront Next). Content assets are platform-agnostic, so you can update content once and have it reflected across all storefronts.
Embed Content in Your Storefront
Use fetchPageWithComponentData and the Region component to load and render content slot page data anywhere in your storefront.
1import { Region } from "@/components/region";2import { fetchPageWithComponentData } from "@/lib/util/pageLoader";3import type { LoaderFunctionArgs } from "react-router";45export function loader(args: LoaderFunctionArgs) {6 return {7 basket: fetchBasket(args.context),8 // Load content slot page data9 shippingInfo: fetchPageWithComponentData(args, { pageId: "checkout-shipping-info" }),10 };11}1213export default function CheckoutPage({ loaderData }) {14 return (15 <div>16 <h1>Checkout</h1>17 {/* Your page content */}1819 {/* Embedded content from Page Designer */}20 <aside className="mt-8">21 <Region page={loaderData.shippingInfo} regionId="content" />22 </aside>23 </div>24 );25}
Content updates in Business Manager are reflected immediately without code changes.
Content Slot Workaround Limitations
No dedicated APIs for content slot management—uses the same fetchPageWithComponentData as regular pages.
No caching or CDN strategies specific to embedded content.
Merchants must navigate to Page Designer to edit content—no inline editing where it’s embedded.
You must create a “page” in Business Manager for content that isn’t actually a full page.
When the “Embedded Content” feature ships, migrate your content slot pages to the new system and update component references to the new API.
Quick Reference
Component Checklist
@Component decorator with id, name, group, description
@AttributeDefinition for each configurable prop
@RegionDefinition if component contains nested regions
export function fallback() - lightweight loading state
export default - main component
export const loader - if data loading needed
Page Checklist
@PageType decorator with name, description, supportedAspectTypes