Experience Sitecore ! | More than 300 articles about the best DXP by Martin Miles

Experience Sitecore !

More than 300 articles about the best DXP by Martin Miles

Blog content

So, don't miss out! Subscribe to this blog/twitter from the buttons above!

Reviewing my 2025 Sitecore MVP contributions

Sitecore Technology MVP 2025

Sitecore Technology MVP 2024 Sitecore Technology MVP 2023 Sitecore Technology MVP 2022 Sitecore Technology MVP 2021

Sitecore Technology MVP 2020 Sitecore Technology MVP 2019 Sitecore Technology MVP 2018 Sitecore Technology MVP 2017


The Sitecore MVP program recognizes individuals who have demonstrated advanced knowledge of the Sitecore platform and a commitment to sharing knowledge and technical expertise with community partners, customers, and prospects over the past year. The program is open to anyone passionate about Sitecore and eager to contribute to the community.

Over the past application year, starting from December 1st, 2024, I have been actively involved in the Sitecore community, contributing in a number of ways.


Sitecore Symposium 2025 Presentation

Together with Vasiliy Fomichev, we led a very insightful 50-minute workshop on building agentic copilots for Sitecore, during which Vasiliy provided the full theoretical foundation for the topic. I took it from there with a practical, hands-on demo of what it takes to make one from zero to the actual work, essentially giving the step-by-step instructions one could reproduce to get this done in under an hour. 

My demo showcased the effort and key decisions required to build a Microsoft Teams copilot, enabling marketers to perform specific operations (mass rebranding in our case, but could be anything) in the fastest, safest way. 

The whole chain looks as follows:

    Ms Teams ==> Teams Bot ==> LLM ==> Custom MCP Server ==> PowerShell ==> SPE (and the same reverse way back)

Recordings are available:

Agentic AI Challenge

Thrilled to be recognized as a Top 2nd Finalist in the Sitecore AI Challenge out of 150 submissions globally!

The AI Visibility app I've built will help SitecoreAI XM Cloud clients optimize their websites for AI within minutes. Like Michelle Boockoff-Bajdek mentioned, it's sometimes surprising to learn the fundamental questions people ask about your brand. Our app takes the guesswork out of AI optimization and helps Sitecore users gain a competitive advantage in digital. 

The app is now being reworked (implementing all the recent changes released after Sym) for review to join the public SitecoreAI Marketplace.

Awarding ceremony recording.

Sitecore Blogs 

This year, I have written 23 blog posts on various topics related to Sitecore, top-notch findings about XM Cloud and other composable products, best practices, tips and tricks, and case studies:

YouTube Videos

I occasionally create video recordings/walkthroughs and upload them to my YouTube channel. Some of them are very valuable, while some others are not much. I don't treat YouTube as a primary channel; instead, I see it as a supporting medium for sharing knowledge. For example, I upload all my user group recordings, public presentations, and other significant footage.

Sitecore User Groups

  1. Last fall, I established and organized the most wanted user group of the year – Sitecore Headless Development UserGroup, educating its ~500 members. This one is very special, since headless development has become the new normal for delivering sites with Sitecore. At the same time, so many professionals feel left behind, unable to keep up with the fast-emerging tech. I put it as my personal goal to run it monthly, helping the community learn and grow “headlessly,” and that is one of my commitments to it. It became the most run and most attended/reviewed event among Sitecore user groups, with eight events organized this year (#11, #12, #13, #14#15#16#17, and #18). All sessions are recorded and publicly available on YouTube, and they are also referenced on the individual event pages.
  2. Organized two Los Angeles Sitecore User Groups (#22 and #23). This user group also has ~500 members.
  3. Presented at several user groups.

GitHub

  • There are plenty of repositories among my contributions that are still meaningful and helpful.
  • Not just repositories I share on GitHub, but also plenty of useful gists.
  • I keep the Awesome Sitecore project up-to-date. This repository has plenty of stars on GitHub and is an integral part of the big Awesome Lists family. If you haven’t heard of Awesome Lists and its significance, I highly recommend reading these articles - first and second.

Support Tickets

  • CS543626, which relates to a broken search in XM Cloud.

MVP Program

  • I participate in most (if not all) of the webinars and MVP Lunches (often in both time zones per event).
  • I think MVP Summit is the best perk of the MVP Program, so never miss it. This year, I’ve learned a lot and also provided feedback to the product teams, as I usually do.
  • I participate in several streams of the Early Access Program, sharing insights with the product team ahead of GA dates.
  • In the past, I have participated in a very honorable activity: reviewing first-time applicants for the MVP Program, which is the first line of evaluation, and carefully matching each first-time applicant against high Sitecore MVP standards. This year, I am also taking part in reviewing.

Sitecore Learning

I have collaborated with the Sitecore Learning team for the past 3-4 years, and this year was no exception: they invited me to work on the XM Cloud Certification Exam version 2025. Unfortunately, I cannot publicly disclose this activity due to the NDA signed. This piece of work was successfully completed in the assigned timeframes.

Sitecore Telegram

  • I am making Telegram a premium-level channel for delivering Sitecore news and materials. Telegram offers a unique set of features that no other software can, and I am leveraging these advantages to provide greater convenience to my subscribers.
  • Started in 2017 as a single channel, it has expanded rapidly and reached 1,100 subscribers!
  • Growth did not stop; it escalated further beyond Sitecore, becoming composable with a dedicated channel for almost any composable product.

    Here they all are:

XM Cloud Daily series

With my dedication to Sitecore's new flagship product, XM Cloud, it was no surprise that I just launched a new XM Cloud Daily series of tips and tricks on social media, which has since evolved into SitecoreAI Daily.

Every day, I post useful tips and tricks about new Sitecore cloud offerings on Twitter/X and LinkedIn. This is what it looks like (a few recent postings):

In general, I am very active on LinkedIn (with ~10K+ followers) and Twitter/X (with almost ~1.3K subscribers), posting multiple times per week, often a few a day. 

Out of curiosity, I used the AI-powered browser Comet to count my posts, and it found 330 LinkedIn Sitecore-related posts since 1 December 2024.

Popularizing AI with Sitecore

In January 2025, I joined Zont Digital - an AI-first Sitecore partner, where all our thinking and operations are driven by this philosophy. Thus, I invented and developed Shift AI, which automates ~80% of the migration from legacy Sitecore XP to the new Sitecore AI XM Cloud.

That wasn't the only effort to make Sitecore an AI-first organization. I can name numerous activities, such as developing (non-official) Sitecore MCP server, Symposium Demo, and multiple PoCs.


... and ironically, AI pays my love back:


Hope that is not a hallucination, haha!

Sitecore PowerShell as a SitecoreAI Marketplace app

I have reverse-engineered the Sitecore PowerShell Extension and reassembled it into a SitecoreAI Marketplace app!

This PoC is essentially a blueprint app. On its own, it is a universally working example. Still, its real benefit comes from this app providing a ready-to-use boilerplate that can be reused to build a variety of specialized SitecoreAI Marketplace apps on top of the SPE approach.

The most awesome feature is that all of your Marketplace context values could be easily passed into a remotely executed PowerShell script as a script parameter: there is a convenient Script Parameters mapping with maramater token preview (so that you never miss the right value!)

Here's what it looks like:

To enable SPE with Remoting:

  1. From SitecoreAI Deploy, add SPE_REMOTING_SECRET environmental CM secret, then re-deploy.
  2. Install a package, which will enable SPE with Remoting: SPE_with_Remoting.zip (3.93 kb)
  3. This package also adds a disabled sitecore\speremoting user with admin rights, which you must enable manually from User Manager

Once this setup is complete, the environment is fully prepared to use the app. The Marketplace app supports multitenancy; however, SPE Remoting must be enabled individually for every environment you intend to work with.


Case Study: Search Solutions Comparison for Sitecore XM Cloud Migration

1. Introduction

This case study presents a high-level comparison of four leading search solutions - CoveoSitecore Search, Algolia, and SearchStax - for a Benelux-based financial organization considering a migration to Sitecore AI. The analysis focuses on licensing costs, implementation effort, potential hidden fees, technical limitations, and the availability of React-based frontend SDKs for each platform. The goal is to provide the necessary information to enable an informed decision on whether to migrate from Sitecore XP and to determine which solution best suits the organization's needs and budget.

The website has the following traffic characteristics, taken into consideration:

  • Annual Traffic: ~700K sessions in 2024 and ~850K sessions in 2023.
  • Components: ~160 unique components.
  • Budget Expectations: under to €10K for a “composable” (external) search provider

Section 4 of this document contains the conclusion and the considered recommendation based on the balance of individual organizations’ parameters.

2. Executive Summary

The following table provides a high-level comparison of the four search solutions:

Feature

Coveo

Sitecore Search

Algolia

SearchStax

Licensing Cost

High (Enterprise-focused)

Medium (Bundled with Sitecore)

Low (Pay-as-you-go)

Medium-High

Implementation Effort   

High

Low to Medium

Medium-High (Custom Integration)

Medium

Ideal Use Case

Complex, personalized search

Native Sitecore experiences + AI

Fast, real-time search

Managed Solr for Sitecore

React SDK

Yes (Atomic React)

Yes (Native SDK)

Yes (InstantSearch)

Yes (UI Kits)

Financial Services Fit

Excellent (Strong security & compliance)

Good (Native integration benefits)

Good (Flexible and secure)

Good (Managed Solr security)

3. Detailed Analysis

3.1. Coveo

Coveo is a powerful, AI-driven enterprise search platform that offers advanced personalization and relevance tuning capabilities. It is a mature product with a strong presence in the Sitecore ecosystem, well-suited for large organizations with complex search requirements.

Licensing and Cost

Coveo's pricing is geared towards enterprise clients and is generally the highest of the four options. The pricing model is based on a combination of query volume and the number of indexed items, with subscriptions typically sold on an annual or multi-year basis.

  • Coveo for Sitecore Plans: The Pro+ plan starts at 200,000 queries per month, while the Enterprise+ plan starts at 300,000 queries per month and offers volume-based pricing. Given the client's traffic, they would likely fall into the lower tiers of these plans.
  • Implementation Cost: A typical enterprise-level deployment, including licensing and professional services, can range from $50,000 to over $100,000 USD. This does not include ongoing maintenance or support costs.
  • Hidden Fees: Additional costs can arise from add-on features such as Generative AI, advanced security, and dedicated technical support. Overages on query limits are handled through a discussion with a customer manager rather than automatic charges, providing some flexibility but also potential for unexpected cost increases.

Implementation Effort

Coveo's integration with Sitecore is well-documented and mature, but it is not a simple plug-and-play solution. The platform's power and flexibility come at the cost of increased complexity.

  • Complexity: Coveo has a steep learning curve and often requires dedicated developer time to configure even moderately complex use cases.
  • Expertise: Successful implementation typically requires specialized knowledge of the Coveo platform, and many organizations opt for professional services from Coveo or a certified partner.
  • Time to Value: The complexity of configuration and optimization can lead to a longer implementation timeline compared to other solutions.

React SDK and Frontend Components

Coveo provides a comprehensive set of tools for building modern search UIs with React.

  • Coveo Atomic React (@coveo/atomic-react): A React wrapper around the core atomic web component library, providing a rich set of components for building search interfaces.
  • Plasma Design System: A React-based design system used in the Coveo Cloud Administration Console, which can be leveraged for a consistent look and feel.

Technical Limitations

While powerful, Coveo does have its limitations.

  • File Size: The maximum size for a single indexed item is approximately 256 MB, which includes metadata and permissions.
  • Configuration Complexity: The platform's extensive features can be difficult to manage, and the documentation is sometimes considered vague or incomplete.
  • Cost at Scale: Although the client's current traffic is low, a significant increase in search queries or indexed content could result in substantial cost increases.

3.2. Sitecore Search

Sitecore Search is the native search solution for the Sitecore ecosystem, designed to provide a seamless and integrated experience. It is an AI-powered, headless platform that focuses on delivering personalized and predictive search results.

Licensing and Cost

Detailed pricing for Sitecore Search is not publicly available and requires a direct quote from Sitecore. However, it is often bundled as part of the unified SitecoreAI (ex. XM Cloud) offering, which can make it a cost-effective option for organizations already invested in the Sitecore ecosystem.

  • Pricing Model: The cost is likely tied to the overall Sitecore contract and may not be broken down as a separate line item. This can simplify budgeting, but also makes it difficult to compare directly with other solutions.
  • Implementation Cost: As a native solution, the initial setup is generally more straightforward than third-party integrations. However, customization and optimization will still require development effort.
  • Hidden Fees: Potential hidden costs could arise if the bundled search capacity is exceeded.

Implementation Effort

Sitecore Search is designed for seamless integration with XM Cloud, which should reduce the initial implementation effort compared to third-party solutions.

  • Native Integration: The platform is designed to seamlessly integrate with Sitecore's content models and personalization features, streamlining the integration process.
  • Developer Expertise: Implementation can typically be handled by developers with standard Sitecore expertise, without requiring specialized third-party knowledge.
  • Time to Value: Native integration and a familiar development environment can lead to a faster time to value for most projects.

React SDK and Frontend Components

Sitecore provides a native and well-supported React SDK for building search experiences.

  • Sitecore Search JS SDK for React: A dedicated SDK that allows developers to quickly integrate search experiences into React applications. It includes a full set of UI components and a starter kit to accelerate development.

Technical Limitations

As a relatively new product, Sitecore Search has some limitations and operational challenges that need to be considered.

  • Indexing Delays: Crawling content from multiple sites with a single source can lead to prolonged indexing times, sometimes exceeding an hour. This can be a significant issue for time-sensitive content.
  • Scalability: For large, multi-site implementations, it is recommended to create separate sources for each site to improve indexing efficiency. This adds a layer of management complexity.
  • Real-Time Updates: The platform currently relies on full crawls for index updates, and there is a lack of a "Push API" for immediate, incremental updates. This can result in a delay of several minutes for new content to appear in search results.

3.3. Algolia

Algolia is a developer-focused search-as-a-service platform known for its speed and real-time capabilities. It provides a flexible and powerful set of APIs that enable the creation of fast and responsive search experiences.

Licensing and Cost

Algolia's pricing is transparent and based on a pay-as-you-go model, making it very cost-effective for organizations with low to moderate search traffic. For the client's current traffic levels, the costs would be minimal.

  • Pricing Model: The Grow and Grow Plus plans offer a free tier of 10,000 search requests per month, with additional requests billed at a low rate of $1,000 per 1,000 requests. The number of records (~350 pages) is well within the free tier of 100,000 records.
  • Cost Estimate: Based on the client's average annual traffic of ~775,000 sessions, the estimated annual licensing cost for Algolia would be between $17 and $197 USD, depending on the plan and the actual search rate.
  • Hidden Fees: The primary "hidden" cost with Algolia is the implementation effort, as there is no native Sitecore connector. While the licensing is inexpensive at this scale, a significant increase in traffic or a move to the enterprise Elevate plan could result in substantial cost increases, with average enterprise plans costing around $350,000 annually.

Implementation Effort

While Algolia is known for its developer-friendly APIs, the lack of a native Sitecore connector means that integration requires custom development.

  • Custom Integration: Implementing Algolia with Sitecore requires building a custom integration to index content and create the search interface. This can be a time-consuming and expensive process.
  • Third-Party Connectors: Third-party connectors are available, such as the "Algolia Index Builder for Sitecore" by Brimit, which can simplify the integration process. However, these connectors may come with their own licensing costs and support limitations.
  • Developer Expertise: The implementation requires developers with experience in both Sitecore and API-based integrations.

React SDK and Frontend Components

Algolia offers an actively maintained open-source React library.

  • React InstantSearch (react-instantsearch): A comprehensive library that lets developers create an instant search result experience with a rich set of pre-built widgets. It is highly performant and customizable.

Technical Limitations

Algolia's focus on speed and simplicity comes with some trade-offs.

  • Manual Tuning: Achieving high search relevance often requires manual tuning and configuration of the search algorithm.
  • eCommerce Features: While it can be used for e-commerce, it has limited specialized features compared to platforms like Coveo.
  • Indexation Time: Some users have reported that indexation time can be a factor that impacts user experience, particularly for large and complex datasets.

3.4. SearchStax

SearchStax offers both a fully managed site search solution (Site Search) and a managed Apache Solr hosting service (Managed Search). For a Sitecore XM Cloud implementation, the Site Search product is the most relevant, as it is designed to integrate directly with modern, headless architectures.

Licensing and Cost

SearchStax Site Search pricing is based on a tiered subscription model, with the entry-level Essential plan starting at $799 per month (billed annually).

  • Pricing Model: The plans scale based on the number of indexed items, monthly searches, and advanced features. The Advanced and Premium plans require a custom quote.
  • Implementation Cost: The cost of implementation is moderate, as SearchStax provides a dedicated Sitecore module and UI kits to accelerate development.
  • Hidden Fees: Additional costs could arise from overages on search requests or indexed items, or from the need for advanced security and support add-ons available with the Managed Search product.

Implementation Effort

SearchStax has invested in creating a smooth integration experience for Sitecore users, including those on XM Cloud.

  • Sitecore Integration: SearchStax offers a dedicated module for Sitecore, which connects directly to the Site Search solution, as well as connectors for their Managed Search product.
  • Developer Expertise: The availability of UI kits and pre-built components reduces the required level of specialized expertise, allowing developers with standard React and Sitecore knowledge to implement the solution effectively.
  • Time to Value: The combination of a dedicated Sitecore module and React UI kits can significantly accelerate the development process and reduce the time to value.

React SDK and Frontend Components

SearchStax provides a comprehensive set of tools for building search interfaces with React.

  • Search UI Kits: SearchStax offers UI kits for JavaScript, Vue, Angular, and React/Next.js, which include pre-built components to streamline the development of the search UI.

Technical Limitations

SearchStax has some service limits in place to ensure stability and performance.

  • API and Document Limits: There are limits on API requests per second (20+), document size (100KB), and payload size (10MB).
  • Feature Limits: There are also limits on the number of facet values (50), promoted items (10), and other features.
  • User-Reported Issues: Some users have reported that the platform can be expensive and that there are limitations on the number of search results that can be displayed per category.

4. Conclusion and Recommendations

Each of the four search solutions offers a viable path for a Sitecore XM Cloud migration, but they cater to different priorities and budgets. The availability of React-based SDKs and component libraries from all four vendors is a significant advantage, as it simplifies the development of the front-end search experience.

  1. Coveo remains the top-tier enterprise solution, offering the most advanced AI and personalization features. Its high cost is justified by its power and its proven track record in the financial services industry.
  2. Sitecore Search provides the tightest integration with the SitecoreAI ecosystem, which can lead to a more streamlined implementation and a unified user experience.
  3. Algolia is the most budget-friendly option for the client's current traffic, but the lack of a native Sitecore connector and some basic features introduces significant implementation risk and long-term maintenance overhead.
  4. SearchStax presents a compelling middle ground. It offers a robust, AI-powered search solution with a clear integration path for Sitecore XM Cloud and a more accessible price point than Coveo. Its managed Solr foundation provides a high degree of security and reliability.

Recommendations

  1. Primary Recommendation: Sitecore Search.It should be considered a seamless, all-in-one solution from a single vendor, thus natively fits in the product space. A thorough proof of concept is essential to validate that its performance and scalability meet the client's needs. Native integration and the presence of the best-breed front-end components make this choice the best balance among these platforms. It totally fits the aligned budget. Additionally, it features AI personalization capabilities and operates within the newly created Unified Data, alongside XM Cloud (for tracking, analytics, personalization, and more).
  2. For a financial institution that prioritizes a premium, secure, and highly personalized user experience, Coveo could be a recommended solution. Its enterprise-grade features and strong compliance posture are well-suited to the needs of the financial services industry. However, due to budget concerns, Coveo is not a suitable option. Coveo's minimal tier times exceed the organization’s desired budget range.
  3. Strong Alternative: SearchStax.If the cost of Coveo is a significant barrier, SearchStax is a strong alternative. It provides a powerful, AI-driven search experience with a supported integration path for Sitecore XM Cloud. Its balance of features, cost, and ease of implementation makes it a very attractive option. However, despite being a budget option, the total cost of ownership can often be higher compared with Sitecore Search and Algolia.
  4. Budget-Constrained Option: Algolia.Algolia should only be considered if the budget is the primary driver, and the organization has a strong in-house development team to manage custom integration. The long-term total cost of ownership may be higher than the initial licensing fees suggest.

The choice between Sitecore Search and SearchStax will likely come down to a trade-off between the advanced, integrated features of the native Sitecore product and yet still powerful solution offered by SearchStax.

5. References

The Game Has Changed with Sitecore AI and the Dawn of the Agentic Era

For years, I’ve been navigating the ever-evolving landscape of Sitecore, and I’ve witnessed my fair share of pivotal moments. From the shift to Helix to the dawn of the composable DXP with XM Cloud, we’ve adapted and grown. But let me tell you, what I saw unfold at Sitecore Symposium 2025 feels different. This isn’t just another incremental update or a new product bolted on the side. This is a fundamental rewiring of the platform’s DNA. Sitecore has officially planted its flag, not just in the AI-powered future, but in the agentic era.

Let’s be honest: the buzz around AI has been deafening, and for a while, it felt like every tech company was just scrambling to add a "copilot" to their UI. I’ve been cautiously optimistic, waiting for a vendor to show a truly integrated, enterprise-ready vision. After seeing the announcements from Symposium, I can say that Sitecore has stepped up and delivered a cohesive, powerful, and surprisingly practical platform for this new reality.

The Writing on the Wall: It’s Not Your Website Anymore

CEO Eric Stine set the stage perfectly during his opening keynote. He confronted a reality that many of us in the content and marketing world are grappling with: customer journeys are no longer starting with a Google search that leads to our beautifully crafted homepages. They’re starting in social media feeds, and increasingly, in the summarized answers of generative AI models. Eric delivered a line that will stick with me:

Our content isn’t driving traffic anymore. Our content is the traffic.
This single statement encapsulates the existential shift we’re facing. If our content is being consumed, summarized, and re-packaged by AI before a user ever reaches our domain, how do we maintain control of our brand’s narrative and experience? Sitecore’s answer is not to fight this trend, but to build a platform that thrives in it. That platform is SitecoreAI.

SitecoreAI is the New Foundation

First things first, SitecoreAI is not just a new set of features; it’s the new name and foundation for Sitecore’s entire composable DXP. It represents the formal unification of XM Cloud, Content Hub DAM, CDP & Personalize, as well as Search, into a single, AI-enabled SaaS platform. For existing XM Cloud customers, the best part is that this transition is automatic, with no migration or new contract required.

This move addresses a major pain point many of us have felt: the complexity of a composable stack. By bringing everything under one roof with a single data model and workflow, Sitecore is finally delivering on the promise of composable without the fragmentation.

A New Commercial Model: Power Without Punishment

Perhaps the most surprising and welcome announcement came from COO Dave Tilbury. He acknowledged the painful reality of enterprise software procurement and announced a radical simplification of Sitecore’s commercial model.

The key takeaways are transformative:

  1. Simplified Pricing: Every major capability now has a single metric driving its price. No more juggling page views, API calls, and bandwidth caps.
  2. Full Suite Access: When you buy one module, you get production-scale access to the entire SitecoreAI suite (CMS, DAM, Personalization, etc.). You can experiment and prove value before committing to a broader rollout.
  3. AI is Included: In a world where competitors are selling AI by the token, Sitecore has made a bold move. All AI agents, copilots, and workflows are included. No upsells, no credits, no games.

This commitment to simplicity and value is a massive statement of confidence in the platform and a huge win for the entire Sitecore community.

The Rise of the Agents: Moving from Copilots to Autonomous Teams

The most profound shift introduced with SitecoreAI is the move from simple copilots to true agentic AI. An agent is more than just a chatbot that answers questions; it’s an autonomous entity that can understand a goal, create a plan, and execute multi-step tasks to achieve it.

SitecoreAI ships with 20(!) pre-built agents out of the box, ready to automate complex workflows. We’re talking about things like:

  • Migration Tooling Agents: Used by brands like Regal Rexnord and Hexagon to consolidate dozens of legacy sites, cutting migration timelines from months to weeks.
  • Contextually Aware Content Agents: Leveraged by Berkeley Homes and AFL to generate highly targeted content for specific audiences and channels.
  • Campaign & Strategy Agents: Capable of drafting creative briefs, identifying audiences, and even optimizing budgets.
These agents work within Agentic Flows and Spaces inside the Agentic Studio, creating a collaborative environment where marketers can direct, review, and approve the work being done by their new AI team members.

Under the Hood - How the Magic Actually Works

For the technical folks like me, this is where it gets really interesting. This isn’t just black-box magic; it’s built on a robust and open architecture. The key is the decent variety of Unified APIs along with Marketer MCP (Model Context Protocol).

The MCP acts as a secure bridge, translating natural language requests from a marketer into concrete actions. When a marketer asks an agent to “create a new landing page for the summer campaign with a personalized banner for returning visitors,” the MCP interprets this request and uses the Agent API to execute the necessary steps in Sitecore: creating the page, adding the components, applying the personalization rule, and so on.

Each "tool" an agent can use corresponds to a secure, governed endpoint in the Agent API, covering everything from site management and content creation to personalization. This provides the perfect blend of power and safety, ensuring that AI agents operate within the same permission-based framework as human users.

The First User Experience and the New User Interface

Upon the very first run, you will receive these introduction popups:

Now let's take a look at the new way of the tools organization.

1. Strategy

Strategy in SitecoreAI unifies planning, collaboration, and delivery in a single workspace. Marketers can move from brief to campaign to deliverables and tasks without switching tools, with AI enhancing every step. Strategy acts as the planning front door to Sitecore’s marketing cloud, linking creative and operational workflows across teams.

Work is often planned in scattered docs, sheets, or project tools, while execution lives inside Sitecore. Teams lack one place to see what is planned, what is due, and what is blocked across campaigns and briefs. Strategy provides that shared view and gives AI a clear surface to help with planning, prioritization, and decision making.

  • Overview, a central dashboard for campaign planning that shows pinned sites, a snapshot of site analytics, upcoming campaigns, a briefs tracker, and a lightweight deliverables calendar.

  • Assistant is used to generate briefs directly in the brand-aware assistant chat using natural language, publish them right away, then refine details in the Briefs workspace.

    Briefs allows you create, view, and edit briefs made manually or with AI in a single editor page. Link related campaigns, add comments, assign tasks, and convert approved briefs into draft campaigns with one click.

    Campaigns lets you manage every campaign in one place. Review campaigns converted from briefs or created manually, add deliverables and tasks, assign owners, and set timelines to track progress.

2. Channels

In SitecoreAI, Channels is the primary workspace for building and managing digital experiences, it centralizes everything needed to create and organize sites and site collections. You open it from the navigation menu by selecting Channels. Within Channels, teams can create and manage sites from templates or copies, adjust site settings, and open sites in Page Builder for content updates. They can also create and manage site collections to group related sites for shared resources and organized projects, build web pages in Page Builder to design, edit, and personalize with components and content, and personalize and test experiences by creating page variants and running A/B/n tests on components.

An Agentic studio widget sits below the navigation menu, providing entry to agentic features in Agentic Studio. To use these agentic features, Stream must be enabled in the Sitecore Cloud Portal, if it is not enabled, click Enable Stream in Cloud Portal and follow the on screen steps.

3. Design

SitecoreAI Design is a unified workspace that brings together the Design studio, components, forms, and brand kits so teams can create, configure, and publish reusable building blocks for Page builder. From the Design sidebar, users can see totals for draft and live items, open full lists, adjust visualization values, generate variants with AI, and access the Agentic studio widget. To use agentic features, Stream must be enabled in the Sitecore Cloud Portal. Forms can be built or templated and activated in Page builder, and brand kits align AI generated content to brand guidelines through uploaded source documents and access controls.

The Design studio itself is a centralized interface for visualizing and testing components and forms outside any specific site. It lets teams compare components and their variants side by side, experiment with design and content configurations using standard values, mock data, or temporary settings, simulate responsive breakpoints, and preview how different data sources render, including GraphQL. Changes made here are not saved, but they inform final configurations in Pages or the Content Editor. Full access requires Content SDK version 1.1.0 or later and that Stream is enabled.

Key benefits include AI powered generation of component variants to accelerate prototyping, reduce repetitive setup, and explore alternative styling and structure while encouraging accessibility and consistency. The studio improves discovery and coherence by letting teams browse components across sites, search with filtering, compare variants, and see how components render per site. It also provides a safe space for real time testing of field values, layout, styling, and responsiveness across devices, plus the option to access component code to explore AI assisted improvements, with insights feeding into final Page builder setups. 

4. Performance

SitecoreAI Performance gives one place to monitor how experiences perform across sites, forms, and experiments, and to measure the impact of changes. You must first create an analytics identifier and assign it to your site, you can use the same identifier across multiple sites to consolidate data. The Performance entry point summarizes activity and links to the Sites, Forms, and A/B/n tests dashboards, with Search, Events, and Traffic marked as coming soon. You can also turn on a Demo switch to view mock data. Additional views include Page insights in Analyze for page level analytics and a customizable Sites dashboard per site.

The Sites performance dashboard tracks visitors, average time on site, visits, bounce rate, plus time series for views and visitors, and visual breakdowns by browser, operating system, top countries, visits by time of day, and source. It opens from Performance, supports choosing a site and time range, and auto refreshes every minute. Notes clarify that a visit spans all actions until close or inactivity, the time series includes both active and closed visits so totals cannot be summed, and country data is IP based and can be skewed by VPNs.

The Forms performance dashboard automatically collects data from all active forms used in Pages and Components, and lets you filter by site, time, and specific form. It reports form views, form interactions, interaction rate, submissions, and submission rate, using VIEWED, INTERACTION, and SUBMITTED events, highlights up or down trends, auto refreshes every 15 minutes, and supports data export as a ZIP. 

The A/B/n tests performance dashboard shows status, primary goal performance against a target, days running, total unique visits, and a goals by visits table. Filters include goal over time, device, and time window, with an overview chart and a details table that lists variant name, visits, selected goal value with a 95 percent margin of error, goal metric uplift with margin of error, and a confidence index that is valid only after minimum sample size is reached. Test analytics appear after at least 24 hours and a page republish, and you can also view a quick snapshot from the page builder or the site dashboard. Page insights in Analyze lets you pick a site, language, and time period, then view or compare a page with one of its variants side by side, with metrics for visitors, average page views per session, views, a visits chart, visits by time of day heatmap, variant views, top countries, source, browser, and operating system, and it refreshes every minute after the initial load.

What is especially exciting, we're getting Search performance metric soon, right from the same unified interface.

5. Agentic

Agentic studio in SitecoreAI is a workspace where marketers collaborate with AI to ideate, brief, plan, and execute work through autonomous agents, with Stream required to be enabled in the Sitecore Cloud Portal. From anywhere in the platform you can open Agentic via the navigation or the AI icon, then use the Overview page to delegate tasks, access recent work, and jump into Actions, Featured Agents, Featured Flows, and the latest Signals. Actions supports natural language prompts, file attachments, and optional brand knowledge context, and it can auto select the right agent, prioritize speed, or let you choose a specific agent, while preserving chat history for continuity.

Agents are the core automation units, essentially digital workers that act toward goals, make decisions, coordinate with other agents, and learn from feedback, with built in options for research, AEO or SEO analysis, content and email generation, translation, summarization, account enrichment, structured extraction, and more. The Agents page lists all out of the box and custom agents, supports running them directly, and, for users with a Builder License, allows creating, duplicating, deleting, and editing agent configurations.

Flows automate larger multi step processes by chaining one or more agents, maintaining context through each stage, passing outputs between agents, and inserting human checkpoints where needed. The Flows page lets teams browse by category, run flows, and track them, with examples like ABM campaign, Adaptive optimization, and Context aware content that accelerate common scenarios.

Signals provide daily, AI curated market insights based on your preferences, surfacing timely indicators from trusted sources so teams can understand trends, spot gaps, and prioritize actions. Spaces organize all agent and flow executions into dedicated pages that capture status, history, outputs, and collaboration details, giving a single place to review, continue, and manage work across campaigns.

Agentic must be provisioned for you organization in advance, otherwise the only you'll see would be the below screen:

But the unification is just the table stakes. The real game-changer is the engine that powers it all: Sitecore Studio.

A Tour of Sitecore Studio

Sitecore Studio is the unified extensibility framework for the entire SitecoreAI platform. It’s the command center where marketers, developers, and AI collaborate. It’s not a single tool, but a collection of four distinct, yet interconnected, workspaces.

Studio Component  Role & PurposeKey Audience
Agentic StudioA no-code workspace to design, govern, and orchestrate AI agents that automate marketing workflows from planning to optimization.Marketers
App StudioA developer-focused hub to build, configure, and deploy custom apps, extensions, and agents using APIs, SDKs, and the Model Context Protocol (MCP).Developers & Partners
MarketplaceAn app store for discovering and installing public and private apps and agents, providing a native, secure experience.Marketers & Developers
Sitecore ConnectAn integration workbench (powered by Workato) with a library of pre-built connectors and recipes to connect SitecoreAI to the broader tech stack.Developers & Integrators

This above structure is brilliant. It provides a clear separation of concerns while fostering collaboration. Marketers get the safe, no-code environment they need to innovate at speed in Agentic Studio, while developers are empowered to extend the platform’s core capabilities in App Studio.

The Road Ahead: What This Means for Us

The launch of SitecoreAI and Sitecore Studio is more than just a product release; it’s a paradigm shift. It’s a clear signal that Sitecore understands the future of digital experiences is not about building better websites, but about orchestrating intelligent, personalized interactions across a vast, fragmented landscape.

For marketers, this is a moment of empowerment. It’s the chance to move from being a task manager to a strategic orchestrator, using AI as a force multiplier to achieve business goals faster than ever before.

For developers, this is a new frontier of extensibility. App Studio, the Marketplace, and the MCP open up incredible opportunities to build and monetize new capabilities, solving unique business challenges on a secure, scalable platform. I’ve been in this space for a long time, and it’s rare to see a vision this bold executed with such clarity and completeness. The future of digital marketing is here, and it’s agentic.

It’s time to get our hands dirty and start building!

The Future is Now: Sitecore Content SDK 1.2 brings App Router into XM Cloud

For years, I’ve been navigating the ever-evolving landscape of Sitecore, and I’ve seen my fair share of game-changing updates. But let me tell you, the recent release of Sitecore Content SDK v1.2 feels different. This isn’t just another incremental update; it’s a fundamental shift in how we build for XM Cloud, and it’s bringing the power of the Next.js App Router to the forefront of Sitecore development. I’ve had the chance to dive deep into this release, and I’m thrilled to share my findings with you.

The Writing on the Wall: JSS, Content SDK, and the XM Cloud Trajectory

Let’s be honest: the transition to a composable DXP has been a journey. We’ve all been wondering about the future of JSS and how it fits into the XM Cloud picture. Well, Sitecore has made its stance crystal clear: the Content SDK is the only way to go for new XM Cloud projects.
Sitecore’s official support lifecycle KB article outlines everything.

Here’s the key takeaway:

JSS SDK 22.X will reach its end-of-life (EOL) in June 2026.
This means if you’re on JSS with XM Cloud, it’s time to start planning your upgrade. JSS will continue to be the SDK for on-premise XM/XP deployments, but for the cloud, the Content SDK is the designated path forward. This isn’t a bad thing - in fact, it’s a massive leap in the right direction.

Why the Content SDK is a Game-Changer

I’ve spent some time with the Content SDK, and I can tell you firsthand that it’s more than just a rebrand of JSS. It’s a leaner, meaner, and more focused toolkit designed specifically for the needs of XM Cloud. The community has been buzzing about this, and for good reason. As my friend at Fishtank puts it, the Content SDK is a major upgrade. Here’s a breakdown of the key differences:

Feature
JSS SDK
Content SDK
Supported Products
Sitecore XM/XP and XM Cloud
Exclusively for XM Cloud
Visual Editing
Experience Editor & XM Cloud Pages
XM Cloud Pages Builder only
Complexity & Size
Larger, more complex starter apps
Significantly smaller and simpler
Component Mapping
Automatic
Manual registration by default
Configuration
Scattered across multiple files
Centralized in sitecore.config.ts and sitecore.cli.config.ts
Data Fetching
Various data fetching plugins
Unified SitecoreClient class
Middleware
Separate middleware plugin files
Simplified with defineMiddleware in middleware.ts

Farewell, Experience Editor

One of the most significant changes is the removal of Experience Editor support. This might sound alarming at first, but it’s a strategic move. By focusing solely on the XM Cloud Pages Builder, the Content SDK sheds a tremendous amount of complexity. This results in a leaner codebase that’s easier to understand, maintain, and, most importantly, faster.

Enter the App Router: A New Era for Next.js in XM Cloud

The headline feature of Content SDK 1.2 is, without a doubt, the introduction of beta support for the Next.js App Router. This is a monumental step forward, aligning XM Cloud development with the latest and greatest from the Next.js ecosystem.
For those unfamiliar, the App Router is a new paradigm in Next.js that simplifies routing, data fetching, and component architecture. It introduces concepts such as server components, nested layouts, and streamlined data fetching, making the building of complex applications more intuitive than ever.
I’ve been exploring the xmcloud-starter-js repository, specifically the release/CSDK-1.2.0 branch, to see how all of this comes together.
Let’s take a look at some of the code.

The New App Router Structure

The folder structure itself tells a story. Gone is the pages directory, replaced by a more intuitive app directory:
src/
├── app/
│   ├── [site]/
│   │   ├── [locale]/
│   │   │   └── [[...path]]/
│   │   │       └── page.tsx
│   │   └── layout.tsx
│   ├── api/
│   ├── layout.tsx
│   ├── not-found.tsx
│   └── global-error.tsx
├── components/
├── lib/
└── middleware.ts
This structure is not only cleaner but also more powerful, allowing for features such as route groups and nested layouts that were previously cumbersome to implement in the Pages Router.

Data Fetching in Server Components

With the App Router, Server Components are the default. This means you can fetch data directly within your components without getServerSideProps or getStaticProps. Here’s a look at the new page.tsx:

// src/app/[site]/[locale]/[[...path]]/page.tsx

import { notFound } from 'next/navigation';
import { draftMode } from 'next/headers';
import client from 'src/lib/sitecore-client';
import Layout from 'src/Layout';

export default async function Page({ params, searchParams }: PageProps) {
  const { site, locale, path } = await params;
  const draft = await draftMode();

  let page;
  if (draft.isEnabled) {
    const editingParams = await searchParams;
    // ... handle preview and design library data
  } else {
    page = await client.getPage(path ?? [], { site, locale });
  }

  if (!page) {
    notFound();
  }

  return <Layout page={page} />;
}
Notice how clean and concise this is. We’re using async/await directly in our component, and Next.js handles the rest. This is a huge win for developer experience.

A New Approach to Layouts

The App Router also introduces a more powerful way to handle layouts. You can now create nested layouts that are automatically applied to child routes. Here’s a simplified example from the starter kit:
// src/app/[site]/layout.tsx

import { draftMode } from 'next/headers';
import Bootstrap from 'src/Bootstrap';

export default async function SiteLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: Promise<{ site: string }>;
}) {
  const { site } = await params;
  const { isEnabled } = await draftMode();

  return (
    <>
      <Bootstrap siteName={site} isPreviewMode={isEnabled} />
      {children}
    </>
  );
}

This SiteLayout component wraps all pages within a given site, providing a consistent structure and allowing for site-specific logic.

Migrating from JSS to the Content SDK: A Checklist

For those of us with existing JSS projects, the migration to the Content SDK is now a top priority. While Sitecore provides a comprehensive migration guide, here’s a high-level checklist to get you started:
  1. Update Dependencies: Replace your jss-nextjscode> packages with the new @sitecore-content-sdk/nextjs packages.
  2. Centralize Configuration: Create sitecore.config.ts and sitecore.cli.config.ts to consolidate your settings.
  3. Refactor Data Fetching: Replace your data fetching logic with the new SitecoreClient class.
  4. Update Middleware: Consolidate your middleware into a single middleware.ts file using the defineMiddleware utility.
  5. Register Components: Manually register your components in the .sitecore/component-map.ts file.
  6. Update CLI Commands: Replace your jss CLI scripts with the new sitecore-tools commands.
  7. Remove Experience Editor Code: Clean up any code related to the Experience Editor, as it’s no longer supported.

This is a non-trivial effort, but the benefits in terms of performance, maintainability, and developer experience are well worth it.

The Rise of AI in Sitecore Development

Another fascinating aspect of the Content SDK is its deep integration with AI-assisted development. The repository now includes guidance files for Claude, GitHub Copilot, and other AI tools. This is more than just a novelty; it’s a serious productivity booster. These guidance files instruct your AI assistant on Sitecore-specific conventions, ensuring that the code it generates adheres to best practices.

I’ve been experimenting with this, and the results are impressive. When I ask my AI assistant to create a new component, it knows to:
  • Use the correct naming conventions.
  • Create the necessary props interface.
  • Use the Sitecore field components (<Text>, <RichText>, etc.).
  • Handle missing fields gracefully.
This is a huge time-saver, ensuring that even junior developers can write high-quality, consistent code.

The Road Ahead

The release of Content SDK 1.2 and the introduction of the App Router mark a pivotal moment for Sitecore XM Cloud. It’s a clear signal that Sitecore is fully committed to modern, composable architecture and is dedicated to delivering a world-class developer experience.
For those of us who have been in the Sitecore trenches for years, this is an exciting time. We’re seeing the platform evolve in ways that will allow us to build faster, more robust, and more engaging digital experiences than ever before. The road ahead is bright, and I, for one, can’t wait to see what we build with these new tools.

References

The new and shiny Sitecore Marketplace

For years, the Sitecore community has been the platform's secret weapon. We've built countless modules, shared our knowledge at SUGCONs, and pushed the boundaries of what's possible with this DXP. Today, I'm thrilled to share my experience with the Sitecore Marketplace, which officially launched in 2025 and represents a fundamental shift in how we extend and customize Sitecore in the composable era.

I've had the privilege of participating in the Early Access Program and recently submitted a proposal for the Sitecore AI Challenge that made it to the finals. Today, I'm completing the final submission, and I can tell you firsthand: this is not just another feature release. The Marketplace is a strategic bet on the community, a multiplication of our collective effort, and a recognition that Sitecore's greatest strength has always been its people.

In this comprehensive guide, I'll walk you through everything you need to know to build production-ready Marketplace apps, from arch.


Why the Marketplace Matters: The Strategic Context

Let's be honest: the shift to SaaS has been challenging for many of us who built our careers on the extensibility of Sitecore XP. We could customize anything, extend everything, and build solutions that were uniquely tailored to our clients' needs. When XM Cloud launched, there was a legitimate concern: how do we maintain that level of customization in a managed SaaS environment?

The Marketplace is Sitecore's answer to that question. It's a way to preserve the extensibility we love while embracing the benefits of SaaS. More importantly, it's a recognition that the community is the engine of innovation. By providing us with the tools to build and share apps, Sitecore is effectively multiplying their own development capacity by the size of the community. That's brilliant.

The Developer Studio: Your Starting Point

Your journey begins in the Developer Studio, a new section in the Sitecore Cloud Portal. This is where you'll create and configure your apps. The interface is clean and intuitive, but there are some important decisions to make:

Creating Your App

When you create a new app, you'll need to provide:
  • App Name: This appears in the Marketplace and to end users.
  • Description: Make it clear and compelling.
  • Logo URL: This is mandatory. Your logo needs to be hosted somewhere accessible.
  • Extension Points: Where your app will appear in the Sitecore UI.
  • API Access: Which Sitecore APIs your app needs to call.
  • Deployment URL: Where your app is hosted.
It's important to note that you host your own apps. Sitecore provides the SDK and the integration points, but the hosting is entirely up to you. This gives you complete control over your technology stack, deployment pipeline, and scaling strategy. I'm hosting my AI Challenge app on Vercel, which has been seamless.

App Types: Custom vs. Public

Currently, you can build Custom Apps, which are available to your organization and any other organizations you explicitly authorize. Public Apps, which will be available to all Sitecore customers through the Marketplace, are coming in a later release. Public apps will undergo a quality review process, which is a good thing for the ecosystem.

Architecture: Making the Right Choice

The architecture you choose for your Marketplace app has significant implications for what you can build and how complex your development will be. There are two main patterns:

1. Client-Side Architecture

In a client-side architecture, your app runs entirely in the user's browser. All API requests to Sitecore APIs are proxied through the browser using the SDK. This is the simplest option and is ideal for:
  • UI extensions and custom fields
  • Dashboard widgets
  • Simple data visualization
  • Apps that don't require server-side processing
The key advantage is simplicity. You can build a client-side app with just React or Vue, deploy it as a static site, and you're done. The SDK handles all the authentication and communication with Sitecore automatically.

2. Full-Stack Architecture

A full-stack architecture includes both client-side and server-side components. This is necessary when you need to:
  • Make direct server-to-server API calls to Sitecore
  • Integrate with AI services (like OpenAI, Anthropic, etc.)
  • Perform heavy processing or data transformations
  • Implement agentic workflows
  • Store and manage your own data
For full-stack apps, you'll need to use custom authorization with Auth0. This is more complex to set up, but it gives you the flexibility to build sophisticated applications. My AI Challenge submission is a full-stack app because it integrates with multiple AI services and requires server-side orchestration.

3. Authorization: Built-in vs. Custom

The Marketplace SDK supports two authorization patterns:
  • Built-in Authorization: The SDK automatically manages authentication. This is the default and recommended option for client-side apps.
  • Custom Authorization (Auth0): Required for server-side API calls. You'll need to configure Auth0 credentials in the Developer Studio and handle session invalidation when your app is available in multiple organizations.
For your first app, I strongly recommend starting with client-side architecture and built-in authorization. Get something working, understand the SDK, and then move to full-stack if you need to.

Extension Points: Where Your App Lives

Extension points are the designated areas in the Sitecore UI where your app can be displayed. Understanding them is crucial to designing a great user experience.

1. Standalone (Cloud Portal)

Your app appears on the Cloud Portal home page in the "Marketplace apps" section. It opens in a new tab under the navigation header. This is ideal for apps that are used independently of XM Cloud, like reporting dashboards or administrative tools.
Image source: cloud portal app configuration screen

2. XM Cloud Full Screen

Your app is listed in the "Apps" dropdown in the XM Cloud navigation header and appears full screen. This is perfect for apps that need a lot of screen real estate, like content migration tools or complex configuration interfaces.
Image source: cloud portal app configuration screen

3. XM Cloud Page Builder Context Panel

This is one of my favorite extension points. Your app appears in the context panel to the left of the Page Builder canvas. This is ideal for page-level extensions, like:
  • Real-time analytics insights
  • SEO analysis tools
  • Content quality checkers
  • HTML validators
The context panel is always visible while editing a page, so your app is right there when users need it.

4. XM Cloud Page Builder Custom Field

Your app appears in a modal when a user clicks "Open app" on a custom field. This is perfect for:
  • Icon pickers
  • Color pickers
  • External data selectors
  • Media libraries
I've seen some brilliant implementations of this extension point, including a Material UI icon picker with over 10,000 icons.
Image source: cloud portal app configuration screen

5. XM Cloud Dashboard Widget

Your app can be added as a draggable widget to the XM Cloud site dashboard. This is ideal for displaying site-wide metrics, like bounce rates, popular pages, or performance data from third-party analytics tools.

The Marketplace SDK: A Deep Dive

The Sitecore Marketplace SDK is the foundation of all Marketplace development. It's open-source, well-documented, and a pleasure to work with. Let's dive into the details.

1. Package Structure

The SDK is divided into distinct packages:
  • @sitecore-marketplace-sdk/client: Required for all apps. Handles secure communication between your app and Sitecore.
  • @sitecore-marketplace-sdk/xmc: Optional. Provides type-safe interfaces for XM Cloud APIs, including queries, mutations, and subscriptions.

2. Getting Started: The 5-Minute Quickstart

Here's how you can get a basic Marketplace app running in about 5 minutes:

1. Create a new Next.js or Vite app:
npx create-next-app@latest my-marketplace-app
cd my-marketplace-app
2. Install the SDK packages:
npm install @sitecore-marketplace-sdk/client @sitecore-marketplace-sdk/xmc
3. Create a custom hook for the Marketplace client:
// hooks/useMarketplaceClient.ts
import { useEffect, useState } from 'react';
import { ClientSDK } from '@sitecore-marketplace-sdk/client';

export const useMarketplaceClient = () => {
    const [client, setClient] = useState<ClientSDK | null>(null);
    const [isInitialized, setIsInitialized] = useState(false);
    const [error, setError] = useState<Error | null>(null);

    useEffect(() => {
        const initClient = async () => {
            try {
                const sdkClient = new ClientSDK({
                    onError: (err) => {
                        console.error('SDK Error:', err);
                        setError(err);
                    }
                });

                await sdkClient.initialize();
                setClient(sdkClient);
                setIsInitialized(true);
            } catch (err) {
                setError(err as Error);
            }
        };

        initClient();
    }, []);

    return { client, isInitialized, error };
};
4. Use the client in your component:
// app/page.tsx
"use client"
import { useMarketplaceClient } from '@/hooks/useMarketplaceClient';
import { ApplicationContext } from '@sitecore-marketplace-sdk/client';
import { useState, useEffect } from 'react';

export default function Home() {
    const { client, error, isInitialized } = useMarketplaceClient();
    const [appContext, setAppContext] = useState<ApplicationContext | null>(null);

    useEffect(() => {
        if (isInitialized && client) {
            client.query('application.context')
                .then((res) => {
                    if (res.data) {
                        console.log('Application context:', res.data);
                        setAppContext(res.data);
                    }
                })
                .catch((err) => console.error('Query failed:', err));
        }
    }, [isInitialized, client]);

    if (error) {
        return <div>Error initializing SDK: {error.message}</div>;
    }

    if (!isInitialized) {
        return <div>Initializing Marketplace SDK...</div>;
    }

    return (
        <div>
            <h1>My Marketplace App</h1>
            {appContext && (
                <div>
                    <p>Organization: {appContext.organization.name}</p>
                    <p>User: {appContext.user.email}</p>
                </div>
            )}
        </div>
    );
}
That's it. You now have a working Marketplace app that can communicate with Sitecore.

3. Queries, Mutations, and Subscriptions

The SDK provides three main ways to interact with Sitecore APIs

 

1. Queries: Reading Data

Queries are used to retrieve data from Sitecore. Here are some common examples:
// Get application context
const contextResult = await client.query('application.context');

// Get list of sites
const sitesResult = await client.query('sites.list', {
    contextId: appContext.tenant.id
});

// Get a specific page
const pageResult = await client.query('pages.get', {
    contextId: appContext.tenant.id,
    pageId: 'your-page-id'
});


2. Mutations: Writing Data

Mutations are used to create, update, or delete data in Sitecore:
// Create a new template
const templateResult = await client.mutate('templates.create', {
    contextId: appContext.tenant.id,
    name: 'My Custom Template',
    baseTemplates: ['{1930BBEB-7805-471A-A3BE-4858AC7CF696}']
});

// Create a new item
const itemResult = await client.mutate('items.create', {
    contextId: appContext.tenant.id,
    parentId: 'parent-item-id',
    templateId: 'template-id',
    name: 'My New Item',
    fields: {
        Title: 'My Item Title',
        Text: 'My item content'
    }
});

// Delete an item
await client.mutate('items.delete', {
    contextId: appContext.tenant.id,
    itemId: 'item-to-delete'
});


3. Subscriptions: Real-Time Updates

Subscriptions allow your app to receive real-time updates when data changes in Sitecore. This is particularly useful for Page Builder extensions:
// Subscribe to page changes
const unsubscribe = client.subscribe('pages.changed', (data) => {
    console.log('Page changed:', data);
    // Update your UI accordingly
});

// Don't forget to unsubscribe when your component unmounts
useEffect(() => {
    return () => {
        if (unsubscribe) {
            unsubscribe();
        }
    };
}, []);

4. Context Management: Application vs. Pages

The SDK provides two types of context:
Application Context is available in all extension points and includes:
  • Tenant and resource IDs
  • Environment details
  • User information and permissions
  • Organization data
Pages Context is only available in Page Builder extension points and includes:
  • Current page information
  • Site details and configuration
  • Real-time updates via subscriptions
Understanding which context is available in your extension point is crucial for building the right user experience.
Example of both contexts as they feed the Page Content Panel Extension point

Server-Side Logic with Next.js

For full-stack apps, you'll need to make server-side API calls to Sitecore. The SDK provides an experimental server-side client for this purpose:
// app/api/items/route.ts
import { experimental_createXMCClient } from '@sitecore-marketplace-sdk/xmc';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
    try {
        // Get the access token from the Authorization header
        const authHeader = request.headers.get('Authorization');
        if (!authHeader) {
            return NextResponse.json(
                { error: 'Missing authorization' },
                { status: 401 }
            );
        }

        const accessToken = authHeader.replace('Bearer ', '');

        // Get the context ID from the request body
        const { contextId, itemData } = await request.json();

        // Create the XMC client
        const xmcClient = experimental_createXMCClient({
            accessToken,
            contextId
        });

        // Make the API call
        const result = await xmcClient.items.create({
            parentId: itemData.parentId,
            templateId: itemData.templateId,
            name: itemData.name,
            fields: itemData.fields
        });

        return NextResponse.json(result);
    } catch (error) {
        console.error('Server-side API call failed:', error);
        return NextResponse.json(
            { error: 'Failed to create item' },
            { status: 500 }
        );
    }
}
The key pattern here is:
  1. Get the access token from the Authorization header
  2. Get the context ID from the request
  3. Create the XMC client with both
  4. Make your API calls
  5. Handle errors appropriately

Styling: Blok vs. shadcn/ui

Sitecore recommends using Blok, their official design system, for Marketplace apps. Blok ensures your app looks and feels like a native part of Sitecore, and it includes built-in accessibility compliance.

However, many developers (myself included) prefer shadcn/ui for its flexibility and modern design. There's even a project called blok-shadcn that combines the best of both worlds, providing shadcn/ui components styled to match Sitecore's design language.
For my AI Challenge app, I used shadcn/ui with custom Sitecore-inspired theming, and the results have been excellent.

Development Best Practices

After building several Marketplace apps, here are some best practices I've learned:

1. Local Development with Hot Reload

During development, set your deployment URL to https://localhost:3000 (or whatever port you're using). This allows you to test your app in the actual Sitecore UI while developing locally. You'll need to use HTTPS, even locally. For Vite apps, use vite-plugin-mkcert. For Next.js, use mkcert to generate self-signed certificates.

2. Start Simple, Add Complexity Gradually

Don't try to build a full-stack app with AI integration on your first attempt. Start with a simple client-side app that displays some data. Get comfortable with the SDK, understand the extension points, and then add complexity.

3. Leverage TypeScript

The SDK is built with TypeScript, and the type definitions are excellent. Use them. They'll save you hours of debugging and make your code more maintainable.

4. Handle Errors Gracefully

The Marketplace SDK can throw errors for various reasons: network issues, authentication problems, invalid queries, etc. Always handle errors gracefully and provide meaningful feedback to users.

5. Test in Multiple Environments

Make sure your app works in all the environments where it will be used: local, dev, staging, and production. Pay special attention to CORS issues and authentication edge cases.

Hosting and Deployment

Since you host your own apps, you have complete control over your deployment strategy. Here are some popular options:
  • Vercel: Excellent for Next.js apps. Automatic deployments from Git, great performance, generous free tier.
  • Netlify: Great for static sites and Vite apps. Easy to set up, good CI/CD integration.
  • Azure Static Web Apps: Good choice if you're already in the Azure ecosystem.
  • AWS Amplify: Another solid option with good integration with other AWS services.
For my AI Challenge app, I'm using Vercel, and the deployment workflow is seamless: push to Git, and Vercel automatically builds and deploys.

Learning Resources: A New Developer Course

To further support the community, the Sitecore Learning team is releasing a new developer course for the Marketplace. While the course isn't available yet, you can see the announcement from Learning Team on LinkedIn. This is a fantastic initiative that will help onboard even more developers to the Marketplace ecosystem.

My AI Challenge Experience: Lessons Learned

Participating in the AI Challenge has been an incredible learning experience. Our proposal made us to the finals, and today I'm completing the final submission. 

Here are some key lessons I've learned:

  • The Marketplace enables rapid innovation. I was able to go from idea to working prototype in a matter of days, not weeks or months.
  • The SDK is that good.
  • Full-stack architecture is essential for AI apps. If you're building anything that involves AI services, you'll need server-side logic.
  • The experimental XMC client makes this straightforward.
My team and I ended up creting an AI marketplace extension that optimizes any of your page-under-edit for the agentic engines, by creating brand-aware content that will be consumed by agents parsing the site and therefore - affecting its LLM's output. IT also suggests how this page could get optimized according to schema.org markup for the better LLM parsers consumption:

Throughout the challenge, I've been in contact with other developers, sharing ideas and solving problems together. This is what makes Sitecore and its community very special.

What's Next?

The Sitecore Marketplace is more than just a new feature; it's a fundamental shift in how Sitecore approaches product development. By empowering the community to build and share apps, Sitecore is effectively multiplying their own development capacity. This is brilliant strategy.

The community has always been Sitecore's greatest strength. We've built modules, shared knowledge, and pushed the platform forward for years. The Marketplace is Sitecore's way of saying: 

"We trust you. We value you. Let's build the future together."

If you're a Sitecore developer or architect, I encourage you to start exploring the Marketplace today. Build something small, get comfortable with the SDK, and then tackle something more ambitious. The barrier to entry is low, and the potential is enormous.
What will you build? A custom field? A dashboard widget? An AI-powered content assistant? 

The possibilities are endless. I'd love to hear your thoughts.

Resolving broken images issue on XM Cloud starterkit running in local containers

A guide on how to resolve the media problem with the default vanilla StarterKit (foundation head) when images do not show on a site when accessed by a hostname.

Reproducing the problem

  1. Pull the latest starter kit, run init.ps1 , and up.ps1 as normal. Everything is fresh and clean; nothing else than that.
  2. When CM spins up, create a site collection followed by a site with the default name (nextjs-starter) matching the name of the JSS app.
  3. Open the home page in Experience Editor and drop an Image component to that page, upload and choose the image, save, and confirm it looks fine in EE.
  4. Open the home page again on the site: https://nextjs.xmc-starter-js.localhost and see the error

The error

Invalid src prop (https://cm/-/jssmedia/Project/Tenant/Habitat/LA.jpg?h=408&iar=0&w=612&ttc=63890432287&tt=4BBE52A4592C2DBCAE59361096C0E4D3&hash=0CA75E384F533EE5539236785DCF0E22) on `next/image`, hostname "cm" is not configured under images in your `next.config.js`

What happens?

The hostname of a local CM container is applied to the generated media URL (https://cm). That is not right, as CM hostname is not accessible outside of containers, and only works within the internal Docker network at the HTTP protocol, not HTTPS. After playing with the image URL, it was clear it works by a relative path, trimming the hostname from the start. Both URLs below are valid and show the image:

Testing an assumption

I thought if there was a problem on the datasource resolver of the Image component, but the resolver wasn't set. Just for the sake of experiment, decided to explicitly set image component to use `/sitecore/system/Modules/Layout Service/Rendering Contents Resolvers/Datasource Resolver`, since it has the same effect as when not set, along with unchecking Include Server URL in Media URLs settings for that resolver.

And on the resolver, unchecking as below:

That effectively resolved the issue. My guess was valid, so let's now seek a permanent solution.

The working solution

Once the assumption of removing a hostname is proven, let's take it out at the CM level so that it universally applies to your environments and you don't need to precisely set resolvers on each individual component. The below config patch does exactly what we need.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
    <layoutService>
      <configurations>
        <config name="sxa-jss">
          <rendering>
            <renderingContentsResolver>
              <!-- Set the desired values for the JSS configuration -->
              <IncludeServerUrlInMediaUrls>false</IncludeServerUrlInMediaUrls>
            </renderingContentsResolver>
          </rendering>
        </config>
      </configurations>
    </layoutService>
  </sitecore>
</configuration>

That resolved my problem: the desired image loaded well.

Hope this helps you as well!

Changing item ID in XM Cloud from item's context menu

Historically, changing the ID of an item in Sitecore was widely believed to be impossible, particularly within the constraints of XM Cloud.

In the XP era, I experimented with a custom package nearly a decade ago that did successfully change item IDs. However, achieving this required considerable effort: decompiling out-of-the-box DLLs, reverse engineering the code, and then rebuilding DLLs to match various Sitecore versions and dependencies. The process was complex and not ideal, dependent on runtime specifics. I managed to make it function, but lots have changed since then.

With XM Cloud, many of those challenges have been eliminated. Notably, the platform now includes Sitecore PowerShell Extensions (SPE) out of the box. This makes it feasible to develop a universal script that can change the ID of any item in the content tree, invoked directly from the context menu without the need for server-level modifications. All it takes is a simple package containing a single Sitecore item.

Why change ID?

1. Database Merges and Migrations

  • Resolving ID Conflicts During Database Merges: When combining multiple Sitecore databases (e.g., from separate instances or acquisitions), duplicate IDs can occur if items were created independently. Changing the ID of conflicting items in one database allows seamless integration without data loss.
  • Content Migration from Legacy Systems: During upgrades or migrations from older Sitecore versions or other CMS platforms, imported items might have IDs that clash with existing ones. Changing IDs ensures uniqueness while preserving content structure.
  • Multi-Environment Synchronization: If dev, staging, and production environments diverge (e.g., due to unsynced TDS/Unicorn serializations), changing IDs in one environment can align them without recreating everything.
  • Cross-Database Item Transfers: When moving items between master, core, or web databases, ID collisions might arise; changing the ID facilitates clean transfers.

2. Integration with External Systems

  • Aligning with External Data Feeds or APIs: If an external system (e.g., a CRM like Salesforce or a data warehouse) references Sitecore items by GUIDs but uses its own fixed IDs, changing Sitecore's item ID to match the external one ensures synchronization without modifying the external system.
  • Third-Party Tool Compatibility: Some integrations (e.g., e-commerce plugins or analytics tools) might require specific ID formats or mappings; changing IDs bridges mismatches.
  • Bi-Directional Sync with Other Platforms: In setups with real-time syncing (e.g., via Sitecore Data Exchange Framework), ID changes might be needed to resolve sync errors caused by GUID mismatches.
  • Federated Identity Management: For systems integrating Sitecore with identity providers, where user-generated content items need ID alignment for security or tracking.

3. Item Recovery and Error Correction

  • Recovering from Accidental Deletions: If a critical item is deleted (and not sent to the Recycle Bin) but referenced extensively, recreating it with a new ID and updating links/indexes can restore functionality faster than manual fixes, especially if the original ID causes reference breakage.
  • Fixing Overwritten or Forgotten Items in Version Control: In team environments using TDS or Unicorn, if an item is overwritten or omitted during serialization, changing its ID can resolve conflicts and reintegrate it without rebuilding the entire project.
  • Correcting Database Corruption or Duplicates: Rare DB errors (e.g., from failed restores) might create duplicate IDs; changing one item's ID eliminates the duplication.
  • Repairing Broken References After Errors: If an item's ID leads to index or link database issues (e.g., due to partial publishes), changing it and triggering a reference update can fix widespread breakage.

4. Development and Testing Scenarios

  • Simulating ID Conflicts in Testing: Developers might change IDs to test merge scripts, index rebuilds, or reference update pipelines in controlled environments.
  • Refactoring Large Content Trees: During site redesigns, changing IDs of template items or folders can help reorganize without disrupting live content, especially if combined with link repairs.
  • Debugging Custom Modules: To isolate issues in custom code that relies on specific IDs (e.g., caching or workflows), temporarily changing an ID can aid troubleshooting.
  • Performance Optimization Testing: Changing IDs to force index refreshes or cache invalidations in load testing, helping identify bottlenecks.

4. Other creative scenarios

  • Proof of authoring: In certain cases, you may want to intentionally leave a trace or proof of authoring in the item's ID so that you can prove the fact that you've done this job at some stage later. Once working on a questionable project, I used this trick to encode my phonу number as the last digits of the site definition item. This does not affect any functionality, but at the same time cannot be just a random coincidence.
  • Easter eggs: In some mostly non-production cases, you may want to have some fun with issuing creative naming IDs. HEX-based codes allow plenty of creativity there. For example, all these are valid HEX numbers: 
    • Four chars long: BEEF, CAFE, BABE, FACE, CODE, FEED, etc.
    • Eight chars long: DEADFACE, C0FFEEED, C0DEC0DE, BEEFC0DE, etc.
    • Twelve char long: DEADC0FFEEED, DEADFADEBEEF, AD1DA5AD1DA5, etc.

 

Key Features of the PowerShell Module

The PowerShell module provided below delivers the following capabilities:

  • Assigns a new ID to any item: Accepts user input for the new ID, supporting not only standard content items but also templates, media, system items, and more.

  • Processes hierarchical structures: Handles items with children, fields, and sections, while maintaining the integrity of Standard Values for templates.

  • Updates derived content items: Sets the correct TemplateID on all derived items, preventing "object reference not set" errors.

  • Moves and patches descendants: Migrates and updates all child sections and fields under the new template as needed.

  • Refreshes all references: Updates any base templates, field sources, or XML fields that reference the old template.

  • Cache management: Flushes Sitecore caches and, optionally, rebuilds the Link Database and triggers a publish.

  • Efficient querying: Utilizes fast queries to ensure every relevant content item is included.

  • Comprehensive edge case handling: Covers all major scenarios and exceptions.

How It Works

Since Sitecore does not provide an API for changing item IDs directly, the script implements a robust workaround:

  1. Duplicate the source item (with all fields) under a new ID using the SPE API, which supports custom ID assignment.

  2. Move all children from the old item to the newly created item.

  3. Update all references in the database to point from the old ID to the new one.

  4. Delete the original item once all dependencies have been switched.

Note: Due to the item deletion step involved, this script cannot be used on items that originate from resource files; only items stored in a database are eligible.

Usage

Download

[Download package: ChangeItemID-1.0.zip]

Dictionary in XM Cloud

Localization is more than translation - it's about delivering a seamless, culturally relevant experience for every visitor. In Sitecore XM Cloud, dictionary items provide a simple, robust way to centralize UI text and labels for all languages, directly accessible in your Next.js frontend. Below, I’ll walk through the practical setup, usage patterns, and expert recommendations based on Sitecore’s official documentation and proven community practices.

What Are Dictionary Items?

Dictionary items in XM Cloud let you store and manage all your UI phrases centrally.
Instead of hardcoding "Read More", "Submit",  or error messages, you create dictionary keys under your site’s /Dictionary item. Each key holds localized values for every language you support.

Why:
  • Centralized: Update once, used everywhere
  • Multi-language: Add a new language, all keys covered
  • Consistent: No more stray hardcoded strings

When to Use Dictionary vs. Fields

Typically, you would use dictionary entries for generic text reused in many places (e.g., button labels like "Submit", form field placeholders, system messages). For content that might be specific to a single page or component (e.g., a marketing tagline, section heading, or lengthy description), consider making it a field in a content item or datasource rather than a shared dictionary entry. This gives content authors more flexibility to customize text in context. 

A hybrid approach can work too, for example, use a dictionary phrase as a fallback but allow an override via a field in the CMS if the editor wants a custom message in one place.

How Dictionary Items Work in XM Cloud

In XM Cloud, dictionary items are stored at: /sitecore/content/{collection}/{site}/Dictionary and is fetched via GraphQL through the Layout/Dictionary service. Essentially, for each page request, a GraphQL query runs to get all dictionary entries under the site’s dictionary path for the given language. The Next.js SDK’s DictionaryServiceFactory handles this, so you typically don’t need to write this query yourself. If curious, the query filters by the dictionary root item path, language, and the Dictionary Entry template, and returns all key-phrase pairs. Because this data is pulled at request-time (or build-time for static pages), the translations are ready by the time React components render. No client-side extra fetch is needed for dictionary data. It’s included in the page HTML/props payload.

Each dictionary item represents a key (e.g., "read"), and under it, each language version holds the translated phrase.

For multi-site or SXA setups, you can create a shared dictionary (often in a Shared site or at the tenant root), and then set up a fallback so multiple sites reuse the same dictionary keys. On the integration side, XM Cloud provides a Dictionary Service API, available via REST or GraphQL, which populates the dictionary data at build or runtime for your Next.js app.

Sitecore’s Next.js SDK (part of Headless JSS) comes pre-configured to utilize dictionary data for localization. Here’s how the pieces fit together:

  • Next.js Internationalization (i18n) Settings. In your Next.js app’s next.config.js, define the locales your site supports and a default locale. These locales should match the languages enabled in Sitecore. For example:
    i18n: {
      locales: ['en', 'fr-CA', 'es'], 
      defaultLocale: 'en'
    }
    This allows Next.js to handle locale-specific routes, such as /fr-ca/page-name for French Canadian. The defaultLocale should correspond to your site’s default language, often pulled from a config setting of package.json in the Sitecore starters. If you add a new language to Sitecore, update this config and redeploy the app so Next.js knows about the new locale.
  • Page Props and Dictionary Data. The Sitecore Next.js SDK fetches dictionary entries for each page request (or build) and injects them into the page properties. Specifically, the JSS Page Props Factory (a plugin in the Next.js sample app) uses the Dictionary Service to retrieve all dictionary phrases for the current site/language, and includes them as a dictionary object in pageProps. This happens server-side, either at build time for static generation or on the server for SSR, so that the dictionary is ready by the time the React components render.
  • I18n Provider. The Next.js app uses the next-localization library (a lightweight i18n solution) to provide translations. In the app’s custom _app.tsx, an <I18nProvider> is configured to wrap the page component, initialized with the locale and the dictionary data from Sitecore. For example:
    // In _app.tsx
    import { I18nProvider } from 'next-localization';
    function App({ Component, pageProps }) {
      const { dictionary, locale, ...rest } = pageProps;
      return (
        <I18nProvider lngDict={dictionary} locale={locale}>
          <Component {...rest} />
        </I18nProvider>
      );
    }
    Here, pageProps.dictionary contains all key–phrase pairs for the current locale, and pageProps.locale is the language code. The I18nProvider makes a translation function available to all components via React context.
  • Using the Translation Hook. Inside your React components, you use the useI18n() hook (from next-localization) to access the localization context. See the below paragraph for the exact dictionary consumption code sample.

The Single useTranslation Hook Pattern (with Fallback Defaults)

To keep things tidy, many teams prefer a single useTranslations hook. Here’s a pattern that ensures you never show a blank label, even if the dictionary entry is missing, by supplying a fallback default:

import { useI18n } from 'next-localization';

export function useTranslation() {
  const i18n = useI18n();
  // Utility: always show a fallback if dictionary value is missing
  const getTranslation = (key, fallback) => i18n?.t(key) || fallback;

  return {
    readLabel: getTranslation('read', 'Read'),
    submitLabel: getTranslation('submit', 'Submit'),
    // Add more keys as needed
  };
}

// Usage in a component
const translations = useTranslation();

return (
  <div>
    <button>{translations.readLabel}</button>
  </div>
);

Why this is better:

  • No undefined or blank UI if a dictionary key is missing
  • All translations accessible via one hook - simple, scalable
  • Easy to add more keys as your UI grows

Using Shared SXA Dictionaries & Fallback Domains

If you’re using SXA or multiple sites, you can set up a shared dictionary and configure fallback so every site can leverage the same keys.

Setup Steps:

  1. Create a Shared Dictionary. Place it in a shared location, such as /sitecore/content/{collection}/Shared/Dictionary
  2. Set Dictionary Domain. In Sitecore, under your site’s Dictionary item, set the Dictionary Domain field to the shared dictionary’s path. (Official Doc)
  3. Configure Fallback. On your site’s dictionary, enable "fallback domain" to point to the shared dictionary.

In your Next.js app, the Dictionary Service will automatically merge keys from both the site and shared domains. 

Storybook: Mocking Dictionaries for Isolated UI Development

When using Storybook, components expecting dictionary values may break outside the app context. To avoid this, you can mock the next-localization context in .storybook/preview.tsx:

import { I18nProvider } from 'next-localization';

const mockDictionary = {
  read: 'Read',
  submit: 'Submit',
  // Add other keys as needed
};

export const decorators = [
  (Story) => (
    <I18nProvider lngDict={mockDictionary} locale="en">
      <Story />
    </I18nProvider>
  ),
];
Why this matters:
  • Ensures all components render correctly in isolation
  • Lets designers and QA see accurate UI text in stories
  • Helps catch missing dictionary keys before production

Troubleshooting Dictionary Issues

If you encounter an issue where dictionary translations are not appearing in the Next.js app, it is highly likely that it happens because of one of the very frequently missed things. Consider the following checks:
  • Verify Config and App Name. Make sure the Next.js app’s configured site name (app name) matches the Sitecore site name. This is typically set in your app’s package.json (config.appName) or .env and used by the JSS config. If it mismatches Sitecore’s expected name, the dictionary service might look in the wrong place. In XM Cloud projects, the app name is usually the same as your site name in Sitecore.
  • Check Dictionary Domain Path. As noted, ensure the site’s dictionary domain/path settings in Sitecore are correct. If the Dictionary item was renamed or moved, update the site settings or the config patch so the head application knows where to fetch phrases.
  • Publish Content. Confirm that the dictionary items are published to the target environment (Edge). In a development scenario, if using Connected Mode, ensure the dictionary items exist in the expected database. After editing dictionary entries in the Pages or Content Editor interface, run a publish. Unpublished items will not appear in the GraphQL results.
  • For preview mode issues, rebuild the search index. On XM Cloud, indexes are auto-rebuilt on deploy, but if you import items or restore content, an index rebuild might be necessary.
  • Ensure a valid site root is defined. If you see errors like “Valid value for rootItemId not provided” in logs or GraphQL responses, it indicates the dictionary GraphQL service couldn’t auto-resolve the site’s root. Ensure your site template is correct; if fixing it, you can remove any hardcoded rootItemId overrides you may have added during debugging.

Bonus: Dictionary Migration and Conversion SPE Script

The below script copies dictionary items from an old XP database (referred to as old) to the master database of the locally-run XM Cloud environment and also converts Dictionary entries from a custom format of the Habitat website (which many folks have used as a starter kit, regardless) to the XM Cloud format, which is hard-defined by a dictionary template coming from the items resource file:
param(
    [string]$SourceDatabase = "old",
    [string]$SourcePath = "/sitecore/content/Habitat/Global/Dictionary",
    [string]$TargetDatabase = "master",
    [string]$TargetPath = "/sitecore/content/Zont/Habitat/Dictionary"
)

$srcFolderTemplate = "{98E4BDC6-9B43-4EB2-BAA3-D4303C35852E}"
$srcEntryTemplate = "{EC4DD3F2-590D-404B-9189-2A12679749CC}"
$srcPhraseField = "{DDACDD55-5B08-405F-9E58-04F09AED640A}"

$trgFolderTemplate = "{267D9AC7-5D85-4E9D-AF89-99AB296CC218}"
$trgEntryTemplate = "{6D1CD897-1936-4A3A-A511-289A94C2A7B1}"
$trgKeyField = "{580C75A8-C01A-4580-83CB-987776CEB3AF}"
$trgPhraseField = "{2BA3454A-9A9C-4CDF-A9F8-107FD484EB6E}"

function Copy-DictionaryItemsRecursive {
    param(
        [Sitecore.Data.Items.Item]$SrcParent,
        [Sitecore.Data.Items.Item]$TrgParent,
        [Sitecore.Data.Database]$SrcDB,
        [Sitecore.Data.Database]$TrgDB,
        [int]$Depth = 0
    )

    $indent = (" " * ($Depth * 2))
    $children = $SrcParent.GetChildren()
    Write-Output "$indent- Processing source: $($SrcParent.Paths.FullPath) | Child count: $($children.Count)"

    foreach ($child in $children) {
        Write-Output "$indent  - Processing child: $($child.Paths.FullPath) | TemplateID: $($child.TemplateID) | Name: $($child.Name)"
        $templateId = $child.TemplateID.ToString()
        $newItemName = $child.Name
        $newItem = $null

        try {
            # Check if this item already exists by name under TrgParent
            $existingByName = $TrgParent.Children | Where-Object { $_.Name -eq $newItemName }
            if ($existingByName) {
                Write-Output "$indent    - Using existing target item (by name): $($existingByName.Paths.FullPath)"
                $newItem = $existingByName
            } else {
                # Prepare template item
                $templateItem = $null
                if ($templateId -eq $srcFolderTemplate) {
                    $templateItem = $TrgDB.GetTemplate($trgFolderTemplate)
                    Write-Output "$indent    - Using target template (folder): $($templateItem -ne $null)"
                } elseif ($templateId -eq $srcEntryTemplate) {
                    $templateItem = $TrgDB.GetTemplate($trgEntryTemplate)
                    Write-Output "$indent    - Using target template (entry): $($templateItem -ne $null)"
                }
                if (-not $templateItem) { throw "$indent    - ERROR: Target template not found for $newItemName" }

                # Attempt to create under the current TrgParent
                Write-Output "$indent    - Attempting to Add '$newItemName' under $($TrgParent.Paths.FullPath)"
                $newItem = $TrgParent.Add($newItemName, $templateItem)
                if (-not $newItem) { throw "$indent    - ERROR: Failed to add item $newItemName under $($TrgParent.Paths.FullPath)" }
                Write-Output "$indent    - Created item: $($newItem.Paths.FullPath) [ID: $($newItem.ID)]"
            }

            # Recurse or fill entry fields
            if ($templateId -eq $srcFolderTemplate) {
                Write-Output "$indent    - Recursing into folder: $($child.Paths.FullPath)"
                Copy-DictionaryItemsRecursive -SrcParent $child -TrgParent $newItem -SrcDB $SrcDB -TrgDB $TrgDB -Depth ($Depth + 1)
            } elseif ($templateId -eq $srcEntryTemplate) {
                foreach ($lang in $child.Languages) {
                    $srcItemLang = $SrcDB.GetItem($child.ID, $lang)
                    if (-not $srcItemLang) { throw "$indent    - ERROR: Source item language $lang missing for $($child.Paths.FullPath)" }
                    $trgItemLang = $TrgDB.GetItem($newItem.ID, $lang)
                    if (-not $trgItemLang) {
                        $trgItemLang = $newItem.Versions.AddVersion($lang)
                        if (-not $trgItemLang) { throw "$indent    - ERROR: Failed to add language version $lang to $($newItem.Paths.FullPath)" }
                    }
                    $phraseValue = $srcItemLang.Fields[$srcPhraseField].Value
                    $trgItemLang.Editing.BeginEdit()
                    $trgItemLang.Fields[$trgKeyField].Value = $newItemName
                    $trgItemLang.Fields[$trgPhraseField].Value = $phraseValue
                    $trgItemLang.Editing.EndEdit()
                    Write-Output "$indent    - Populated entry ($lang): $($newItem.Paths.FullPath) [ID: $($newItem.ID)]"
                }
            } else {
                Write-Output "$indent    - Skipping unsupported template: $($child.Name) [$templateId]"
            }
        } catch {
            Write-Output "$indent    - ERROR: $($_.Exception.Message) at item $($child.Paths.FullPath)"
            throw
        }
    }
}

try {
    $srcDB = Get-Database $SourceDatabase
    $trgDB = Get-Database $TargetDatabase
    $srcParent = $srcDB.GetItem($SourcePath)
    $trgParent = $trgDB.GetItem($TargetPath)
    Write-Output "Start: Copying dictionary items from $SourcePath [$SourceDatabase] to $TargetPath [$TargetDatabase] ..."
    if (-not $srcParent) { throw "Source parent item not found: $SourcePath in DB: $SourceDatabase" }
    if (-not $trgParent) { throw "Target parent item not found: $TargetPath in DB: $TargetDatabase" }

    Copy-DictionaryItemsRecursive -SrcParent $srcParent -TrgParent $trgParent -SrcDB $srcDB -TrgDB $trgDB -Depth 0
    Write-Output "Dictionary copy completed successfully."
} catch {
    Write-Output "SCRIPT ERROR: $($_.Exception.Message)"
    exit 1
}

Summary & Best Practices

  • Use a single, type-safe useTranslation hook for clarity and safety
  • Always supply fallback defaults to prevent UI errors
  • Prefer shared dictionaries for multi-site projects? Configure fallback domains in Sitecore for reusability
  • Mock dictionary data in Storybook to maintain robust component previews

Hope you find this post helpful!