<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rob Earlam</title>
    <description>The latest articles on DEV Community by Rob Earlam (@robearlam).</description>
    <link>https://dev.to/robearlam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F183039%2F8e08a25e-521f-4a6e-b67a-d4b43c21bd47.png</url>
      <title>DEV Community: Rob Earlam</title>
      <link>https://dev.to/robearlam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/robearlam"/>
    <language>en</language>
    <item>
      <title>I upgraded the SUGCON sites to Content SDK v2 in under 1hr</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/robearlam/i-upgraded-the-sugcon-sites-to-content-sdk-v2-in-under-1hr-db3</link>
      <guid>https://dev.to/robearlam/i-upgraded-the-sugcon-sites-to-content-sdk-v2-in-under-1hr-db3</guid>
      <description>&lt;p&gt;Just a quick blog post about a win I just had. I blogged last month about the process of &lt;a href="https://dev.to/blog/upgrading-the-sugcon-sites-from-jss-to-the-content-sdk"&gt;upgrading the SUGCON sites from JSS to the Content SDK&lt;/a&gt;, and how the sites had been a bit neglected and were running a super old version. I finished the post by promising not to let that happen, and how we were going to ensure we kept up to date with future releases of the Content SDK. Well shortly after v2 of the SDK was released, so I knew I had to get onboard and update the sites to the latest version.&lt;/p&gt;

&lt;p&gt;I decided to see how far AI could get me in the process... and it turns out it basically did it all for me first time. All in all the upgrade took me less than an to go from nothing to an &lt;a href="https://github.com/Sitecore/XM-Cloud-Introduction/pull/585" rel="noopener noreferrer"&gt;open PR&lt;/a&gt; ready for my colleagues to review.&lt;/p&gt;

&lt;p&gt;I did this by leveraging Copilot CLI and the Adversarial Testing feature that it supports. All I did was to create a new branch on my machine, open the root of the repo using the Copilot CLI and give it the following prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please upgrade the SUGCON Site located in this repo to Content SDK v2. You can find the upgrade guide here: https://doc.sitecore.com/sai/en/developers/content-sdk/20/upgrade-content-sdk-1-5-1-next-js-apps-to-version-2-0.html.

Do not make any changes to git, I will do that once I'm happy with the work at the end.

Once you can finished, please run an adversarial test of the changes using both Opus 4.6 and GPT 5.4

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This went away thinking and making changes for a while and came back with the following response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Upgrade Complete — Sugcon2024 → Content SDK v2

  All files changed

  ┌──────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ File │ What changed │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ package.json │ Removed @sitecore-cloudsdk/*; added analytics-core, events, personalize at ^2.0.0; bumped SDK + CLI to ^2.0.0; next → ^16.1.1; @types/node → ^24.10.4 │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ src/Bootstrap.tsx │ CloudSDK().addEvents().initialize() → initContentSdk({config, plugins}) with analyticsPlugin + eventsPlugin │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ src/middleware.ts │ Deleted │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ src/proxy.ts │ Created — Next.js 16 proxy format; *Middleware → *Proxy class names; defineProxy; default export │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ src/components/content-sdk/CdpPageView.tsx │ pageView import: @sitecore-cloudsdk/events/browser → @sitecore-content-sdk/events │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ src/byoc/index.tsx │ Events namespace import: @sitecore-cloudsdk/events/browser → @sitecore-content-sdk/events │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ sitecore.config.ts.example │ SITECORE_EDGE_URL → NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME; PERSONALIZE_MIDDLEWARE_* → PERSONALIZE_PROXY_* │
  ├──────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ .env.remote.example │ Added NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME, SITECORE_EXPERIENCE_EDGE_HOSTNAME, SITECORE_RENDERINGHOST_NAME; renamed PERSONALIZE_MIDDLEWARE_* → PERSONALIZE_PROXY_* │
  └──────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

  Bugs caught by adversarial review

   - Opus
    4.6 caught: BotTrackingProxy imported from the dev branch template but not yet in published v2.0.1 — removed
   - GPT
    5.4 confirmed the above, and also caught: PERSONALIZE_MIDDLEWARE_* env var names in .env.remote.example were misaligned with the updated PERSONALIZE_PROXY_* names in sitecore.config.ts.example — fixed

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this was the first time I'd upgraded a site to v2 of the Content SDK, so I followed the &lt;a href="https://doc.sitecore.com/sai/en/developers/content-sdk/20/upgrade-content-sdk-1-5-1-next-js-apps-to-version-2-0.html" rel="noopener noreferrer"&gt;upgrade guide&lt;/a&gt; myself afterwards to double check the changes it had made to ensure nothing had been missed. Turns out, it nailed it first time!&lt;/p&gt;

&lt;p&gt;The thing I really liked about this was the text output at the bottom above, covering the result of the Adversarial Testing I asked it to complete. It used both &lt;code&gt;Opus 4.5&lt;/code&gt; and also &lt;code&gt;GPT 5.4&lt;/code&gt; to validate the changes it had made, and each model found different issues that needed to be fixed. This is a a super powerful trick as it means you can play models off against each other leveraging the benefits of both to get you where you need to go faster, how cool is that!&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>sitecoreai</category>
      <category>aidevelopment</category>
      <category>adversarialtesting</category>
    </item>
    <item>
      <title>An Introduction to Harness Engineering</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/robearlam/an-introduction-to-harness-engineering-3j9l</link>
      <guid>https://dev.to/robearlam/an-introduction-to-harness-engineering-3j9l</guid>
      <description>&lt;p&gt;So for a decent amount of time now I've been on the Vibe Coding bandwagon, like a large portion of the development community. When it works it really can seem like magic. Too often though it does seem to go off on a tangent, editing unrelated parts of the codebase, or implementing a something in a way that I just wasn't happy with. I felt that it was making me more productive, but I also felt like I spent a good amount of my time chasing the LLM, going back and forth on the same problem and repeatedly prodding it to get to the outcome that I wanted.&lt;/p&gt;

&lt;p&gt;It felt like one of the big problems with this approach was repeatability, now rules files can help here to try and enforce some guidelines for how LLM's interact in certain scenarios, but I was getting sick of constantly having to type prompts like &lt;em&gt;"You are a senior developer with 10yrs of experience yadda yadda"&lt;/em&gt;. I had played around with some Agents, and they were a step in the right direction, but the whole thing was still feeling very manual, in that I had to hand-hold the AI at each step.&lt;/p&gt;

&lt;p&gt;Then last month I read a blog post published by Ryan Lopopolo from the OpenAI Tech Team about &lt;a href="https://openai.com/index/harness-engineering/" rel="noopener noreferrer"&gt;Harness Engineering&lt;/a&gt; and this got me interested. I had heard of people creating teams of Agents, so I decided it was time to jump in. I ended up rebuilding the site you're reading this blog on now using this approach and I wanted to document how I ended up putting it together for anyone else looking to build software this way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Harness Engineering 101
&lt;/h2&gt;

&lt;p&gt;As I said in my &lt;a href="https://dev.to/blog/new-site-who-dis"&gt;previous blog post&lt;/a&gt; the name is pretty apt. The basic concept is that you think of AI like a horse, it's fast and it's powerful, but for the vast amount of people, if you try an ride it bareback then you're going to have a bad time. That's why you need to develop a Harness for the horse, allowing you to make use of the power and speed it provides while being much more in control of where the final destination is.&lt;/p&gt;

&lt;p&gt;The harness also means you can repeatedly ride the horse to different destinations, but with the same ease. Now from time to time you might have to tighten the harness when you realise there's something you're not happy with. You might also make some slight adjustments depending on the journey your taking or the destination. Overall though, the harness remains pretty much the same for each trip. The same is true for Harness Engineering as well. In this case the harness is a series of &lt;strong&gt;agents&lt;/strong&gt; , &lt;strong&gt;roles&lt;/strong&gt; , &lt;strong&gt;artifacts&lt;/strong&gt; , and &lt;strong&gt;workflow standards&lt;/strong&gt; that let you guide execution instead of hoping for a good result.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;workflow standards&lt;/strong&gt; define how everything should function. In my case this covers everything from Next.JS best practices, and testing standards, through to how the agents communicate with each other, and how the current state of the repo is tracked during execution.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;agents&lt;/strong&gt; are autonomous workers, each with a very specific purpose to execute within the system. I keep the actual definition here very light, instead storing most of the definition in the &lt;strong&gt;roles&lt;/strong&gt;. I have the following agents defined currently though:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Orchestrator&lt;/em&gt; — Controls the workflow end to end, decides which stage should run next, invokes subagents, validates handoffs, keeps execution moving in the right order, and bails out if one of the subagents fails.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;PO-Spec&lt;/em&gt; — Turns the original idea or request into a clear feature specification with scope, intent, and acceptance criteria.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Feature Design&lt;/em&gt; — Translates the feature requirements into a design direction, interaction model, and structural approach for the features being built.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Tech Lead&lt;/em&gt; — Converts the spec and design into an implementation plan with technical decisions, architecture guidance, and delivery steps.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Build&lt;/em&gt; — Actually does the coding work - it carries out the implementation work by creating or updating the code and assets needed to deliver the feature.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;QA&lt;/em&gt; — Reviews the output against the specification and expected behaviour, identifies gaps or defects, and decides whether the work is ready or needs to return to Build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;artifacts&lt;/strong&gt; are what is delivered by each if of the agents above, so for the &lt;strong&gt;PO-Spec&lt;/strong&gt; agent, the artifact is the actual spec that it is created. For the &lt;strong&gt;Build&lt;/strong&gt; agent however the artifact would be the code changes themselves.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;roles&lt;/strong&gt; are where the vast majority of the agent logic is maintained and there is a 1-1 relationship from &lt;strong&gt;agents&lt;/strong&gt; to &lt;strong&gt;roles&lt;/strong&gt; meaning all of the agents listed above have a corresponding role definition. These each define things like the responsibilities of the agent, what pre-requisites need to exist before it can run, what areas of the codebase it can look at to perform it's actions, whether it can iterate on itself, which it can says its completed, and a detailed walkthrough of the process it should follow. One of the main benefits with keeping the definitions in role files with skinny agent files that reference them is that it helps to keep my harness &lt;strong&gt;IDE agnostic&lt;/strong&gt; - I can have skinny definitions for agents in Claude, Cursor or VS-Code, but the logic is in the shared role file avoiding repetition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of Harness Engineering
&lt;/h2&gt;

&lt;p&gt;So you might be reading through the items above and wondering why someone would go to the effort of configuring all of this, when you could just start directly talking with your LLM and creating the code for the feature you require. There's a few really nice things you get by following this approach that I want to cover.&lt;/p&gt;

&lt;h3&gt;
  
  
  The shift from prompting to orchestration
&lt;/h3&gt;

&lt;p&gt;One of the main ones for me is the change from having to repeatedly craft prompts to defining a lot of this in advance in the harness. This allows the LLM to take the actual work request and break it down into discrete tasks, and hand them off to tightly bound agents with specific roles and outputs. It means that each agent has a narrow purpose, clear responsibilities, and explicit limits. Defining all of this up front reduces role leakage, keeps outputs focused, and makes the system easier to reason about and improve. If you find the Tech Lead Agent isn't creating a proper plan from the specs for the build agent, then it becomes very easy to tweak that agents role to get the result you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Artifacts, tasks &amp;amp; the backlog
&lt;/h3&gt;

&lt;p&gt;How I run the delivery process using the harness is that I have a backlog of desired features with a very basic high level description. When I want to implement one I have a conversation with an LLM to generate a much more detailed &lt;strong&gt;Task Definition&lt;/strong&gt; with a unique id, which would describe in more detail the feature I want and any guidance for how I think it should and shouldn't work. This task is then passed through all of the agents to generate their artifacts. The nice thing here is that every artifact generated is created keyed with the task id, and stored in the artifacts folder.&lt;/p&gt;

&lt;p&gt;This means that if I want to look back in the future at how the blog feature was implemented, I can refer back to all of the artifacts that were generated by each of the agents to see why it was implemented the way it was. This can also be used as memory for future feature implementations, you can including instructions like &lt;em&gt;"following the same pagination pattern implemented in the blog features"&lt;/em&gt; and the LLM will know how to do that and where to look for the information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repetition, Repetition, Repetition
&lt;/h3&gt;

&lt;p&gt;I keep mentioning the benefit of repetition with the project for future features, but this concept of repetition is actual broader than that. If I want to start a different project tomorrow on a different technology stack, then my existing harness can still help. Lets say I want to build an IOS application tomorrow, now coding standards will obviously need a large rewrite, but the concepts I described above about &lt;strong&gt;agents&lt;/strong&gt; , &lt;strong&gt;roles&lt;/strong&gt; , &lt;strong&gt;artifacts&lt;/strong&gt; , and &lt;strong&gt;workflow standards&lt;/strong&gt; will be largely transferable. I would move them over to the new project and tweak them to get the output tailored to that project. Coming back to the horse analogy, I'm once more tailoring the harness I'm going to be riding with to better suit the journey I'm on and the destination I want to get to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As I built out this harness, I released I was actually recreating a structure that I had seen and worked in at many different companies before when working on software projects. You have each role within the company responsible for producing the artifacts that the next team would use. Now the difference is that all of this is created by AI, and in a fraction of the time!&lt;/p&gt;

&lt;p&gt;Hopefully this has been a good introduction to some of the key elements to Harness Engineering and how it all comes together. As I continue this series I want to deep dive in to each of the topics I've covered above. I want to talk about how you can craft a tightly defined agent and role, how you can enforce contractual boundaries to minimise agentic scope creep, and ensure the orchestrator can validate completion before continuing the execution pipeline. There's going to be lots to cover, so keep an eye out for future articles on this topic coming soon!&lt;/p&gt;

</description>
      <category>aidevelopment</category>
      <category>harnessengineering</category>
      <category>agenticai</category>
    </item>
    <item>
      <title>New Site, Who Dis?</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Mon, 30 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/robearlam/new-site-who-dis-592h</link>
      <guid>https://dev.to/robearlam/new-site-who-dis-592h</guid>
      <description>&lt;p&gt;For anyone who's read my blog posts before, you wont have seen much (if any) content on here about horses, but turns out there's a first for everything. Bear with me though as it looks like I saved my &lt;em&gt;"horse content"&lt;/em&gt; for just the right time.&lt;/p&gt;

&lt;p&gt;Like the majority of the rest of the development community, I've spent the past couple of years both amazed and a little bit terrified about how AI powered development has taken over the industry. I've always been a developer who's excited about learning new things though, and this was a big one I could sink my teeth into.&lt;/p&gt;

&lt;p&gt;Every few years a new technology comes along that I want to learn, and in those cases I have generally rebuilt my personal site that you're on now as a way to put the technology into play. I knew that I wanted to follow the same process for AI based development, but with the rapid pace of advancement in the technology, I was never really sure about when to attack this, until last month when I read a blog post published by Ryan Lopopolo from the OpenAI Tech Team about &lt;a href="https://openai.com/index/harness-engineering/" rel="noopener noreferrer"&gt;Harness Engineering&lt;/a&gt; and I knew now was the time to bite the bullet.&lt;/p&gt;

&lt;p&gt;I'm planning to write much more on this subject as it has been a decent learning curve for me, but it's been some of the most fun I've have writting code (or not writing it as the case maybe), in a very long time!&lt;/p&gt;

&lt;p&gt;The basic concept is that you think of AI like a horse, it's fast and it's powerful, but for the vast amount of people, if you try an ride it bareback then you're going to have a bad time. Thats why you need to develop a Harness for the horse, allowing you to make use of the power and speed it provides while being much more in control of where the final destination is.&lt;/p&gt;

&lt;p&gt;In reality the what you end up building is a team of agents, each with a tightly bound function. They can't stray outside of their designated function, and there is an orchestrator agent who is repsonsible for invoking each of them. The orchestrator is repsonsible for invoking them in the correct order, and also ensuring that they complete succesfully before invoking the next one.&lt;/p&gt;

&lt;p&gt;All of this comes together through a series of markdown files that are used to define how this system comes together. This covers everthing from how the agents themselves function, the different actions they can perform, the files in the repo they have access to in order to perform their job, and how communication and state management is handled throughout all of this.&lt;/p&gt;

&lt;p&gt;I'm planning to write all of this up in the coming weeks, as it's been an amazingly enjoyable learning journey for me to pull it all together and I'm hoping this series will help others looking to build software in the same way. It took a few attempts to get the Harness into a state where I was happy with it, and it is now churning out features for this Next.js site with ease. I do think that when I complete this the next time the process will be much faster with everything I've learned.&lt;/p&gt;

&lt;p&gt;So my aim is write content covering how I built my setup, what actions worked well, and crucially what didn't. We're going to go over the different agents and their roles, artifact generation, human-in-the-loop review process, execution boundaries, the process I went through pulling all of this together and crucially where I want to take it next.&lt;/p&gt;

&lt;p&gt;So I hope you come back for the next post when we start to dig into this exciting topic for real!&lt;/p&gt;

</description>
      <category>personalsite</category>
      <category>aidevelopment</category>
    </item>
    <item>
      <title>Sitecore Search - Debugging Crawling Errors</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Tue, 27 Feb 2024 21:45:06 +0000</pubDate>
      <link>https://dev.to/sitecore/sitecore-search-debugging-crawling-errors-58cl</link>
      <guid>https://dev.to/sitecore/sitecore-search-debugging-crawling-errors-58cl</guid>
      <description>&lt;p&gt;The latest video in my series on #Sitecore #Search was published this week, discussing how you can debug crawling errors.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/jWch9tCePvE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>sitecoresearch</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Sitecore Search SDK - Breaking Change</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Fri, 02 Feb 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/sitecore/sitecore-search-sdk-breaking-change-1bmh</link>
      <guid>https://dev.to/sitecore/sitecore-search-sdk-breaking-change-1bmh</guid>
      <description>&lt;h2&gt;
  
  
  Updating packages in Sitecore’s Developer Portal
&lt;/h2&gt;

&lt;p&gt;Recently my colleague &lt;a href="https://twitter.com/markvanaalst" rel="noopener noreferrer"&gt;Mark van Aalst&lt;/a&gt; was updating the package versions for the &lt;a href="https://developers.sitecore.com/" rel="noopener noreferrer"&gt;Sitecore Developer Portal&lt;/a&gt;. This also included updating the version of the Sitecore Search React SDK from &lt;code&gt;v2.0.0&lt;/code&gt; to &lt;code&gt;v2.2.2&lt;/code&gt;, among other packages that were updated at the same time. Once this had been deployed, we got reports that faceting was no longer working on the search results page. We quickly rolled back and started to look into what had happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking changes in the Faceting UI component
&lt;/h2&gt;

&lt;p&gt;I reached out to the team that owns the SDK and apparently there was a breaking change introduced in a previous version and we needed to update how we were leveraging the UI components being used to render the Search Results page.&lt;/p&gt;

&lt;p&gt;Previously we were wrapping out Facets in the &lt;code&gt;AccordionFacets.Root&lt;/code&gt; component, like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;AccordionFacets.Root defaultFacetTypesExpandedList={facets.map((x) =&amp;gt; x.name)} onFacetValueClick={onFacetClick}&amp;gt;
    ….
&amp;lt;/AccordionFacets.Root&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this approach is no longer valid, we should now be using &lt;code&gt;SearchResultsAccordionFacets&lt;/code&gt; component instead. As follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;SearchResultsAccordionFacets defaultFacetTypesExpandedList={facets.map((x) =&amp;gt; x.name)} onFacetValueClick={onFacetClick}&amp;gt;
    …
&amp;lt;/SearchResultsAccordionFacets&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was a fairly straightforward change, which meant we could bump the Developer Portal up to be running on the latest version of the Search SDK 🎉.&lt;/p&gt;

&lt;p&gt;To see the complete set of changes we had to make for the Developer Portal, you can view the PR that was opened for this fix &lt;a href="https://github.com/Sitecore/developer-portal/pull/641" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>sitecoresearch</category>
    </item>
    <item>
      <title>SUGCON India 2023 goes off with a bang 💥</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Thu, 31 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sitecore/sugcon-india-2023-goes-off-with-a-bang-58hl</link>
      <guid>https://dev.to/sitecore/sugcon-india-2023-goes-off-with-a-bang-58hl</guid>
      <description>&lt;p&gt;Last week I had the pleasure of attending SUGCON India 2023 in Delhi, India. This was the first time we’d run a SUGCON in India since 2019 and it was great to be back once more, interacting with the local Sitecore community. There was a lot of effort in involved in pulling the event off, and I do want to start by thanking all of the &lt;a href="https://india.sugcon.events/Organisation" rel="noopener noreferrer"&gt;organisers&lt;/a&gt; for the time they invested in making this event the success that it was.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flgmabt773o59ug7zt9z9.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flgmabt773o59ug7zt9z9.JPG" alt="SUGCON Organisers with Sitecore attendees" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was privileged to be chosen to deliver one of the keynote sessions this year, where I talked about a recent project I worked on where we integrated Sitecore Search into our &lt;a href="https://developers.sitecore.com/" rel="noopener noreferrer"&gt;Developer Portal&lt;/a&gt;. This was very well received and led to many questions afterwards, and many further conversations throughout the event. It was great to see the amount of interest there is in Sitecore Search from the attendees!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ut8ll43rewgu0fjnqx3.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ut8ll43rewgu0fjnqx3.JPG" alt="Rob Earlam Delivering a keynote session at SUGCON India 2023" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The quality of the sessions that were delivered at the event was of a very high standard. They ranged from high-level sessions covering Composable DXP’s in general and the power they can bring to customers, all the way down to technical deep dives on specific features and use-cases. Some of my highlights were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The session by &lt;a href="https://twitter.com/pieterbrink123" rel="noopener noreferrer"&gt;Pieter Brinkman&lt;/a&gt; titled &lt;em&gt;Digital Experience is a team sport&lt;/em&gt;, where he talked about the different roles that play a part in successful Composable DXP implementation – it’s not just all about the developer!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/in/georgeksmith/" rel="noopener noreferrer"&gt;George Smith&lt;/a&gt; &amp;amp; &lt;a href="https://www.linkedin.com/in/sheetal-k-jain/" rel="noopener noreferrer"&gt;Sheetal Jain&lt;/a&gt; delivered an awesome session called &lt;em&gt;Beyond Buzzwords: Composable Tech and Generative AI for Real&lt;/em&gt;. Here they showed how OrderCloud, Sitecore Content Hub &amp;amp; Dall-E can be combined to allow customers to generate art on the fly and have it printed on a t-shirt for sale in an online store, cool stuff!&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Exploring the Experience Edge GraphQL Schema&lt;/em&gt; was a really interesting session delivered by &lt;a href="https://mastodon.social/@adeneys@hachyderm.io" rel="noopener noreferrer"&gt;Alistair Deneys&lt;/a&gt;. Here he gave a true deep-dive into the schema implemented for Edge and how you can leverage it in some really interesting ways. There’s also a cool surprise at the end of the session that I won’t give away here, but be sure to check it out if you get the chance.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Women in contemplating Darwin's Theory - To Break the Conventional Wheel&lt;/em&gt; was a great session by &lt;a href="https://www.linkedin.com/in/varalakshmi-md-sitecore/" rel="noopener noreferrer"&gt;Varalakshmi M D&lt;/a&gt; &amp;amp; &lt;a href="https://www.linkedin.com/in/raveena-mathur/" rel="noopener noreferrer"&gt;Raveena Mathur&lt;/a&gt; where they talked about the important role women have in ensuring successful outcomes for customers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/iamandycohen" rel="noopener noreferrer"&gt;Andy Cohen&lt;/a&gt; delivered a great session titled &lt;em&gt;Build for XM Cloud according to the Architect of XM Cloud&lt;/em&gt;. Here he talked about the best practices for building with XM Cloud... he might have ruffled some feathers with some of the recommendations, but it was great to see it all layed out!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The closing keynote was also a highly enjoyable part of the event. Each of the representatives from Sitecore (Pieter, Nicole, Andy, Alistair and myself) held a panel discussion and open Q&amp;amp;A session. This gave the attendees the chance to ask any lingering questions that they hadn’t had the chance to ask already. The topics were very wide from specific feature questions on the products through to general questions about the best way that Sitecore can support the local Indian community… and of course the age-old question of Sandboxes and how people can get access to Sitecore’s newer SaaS products – we hear you and are working on a solution!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5oo66ut4yf8lgq5pso2.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5oo66ut4yf8lgq5pso2.JPG" alt="SUGCON India 2023 Closing Keynote Panel Discussion" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As much as I enjoyed everything I mentioned above, as with every event I seem to attend nowadays, the true highlight was getting to interact with the local community we have on the ground. It’s amazing to see the passion they have for Sitecore and our products. It was great to see so many familiar faces from the events back in 2018 &amp;amp; 2019, but it was also great to see so many new faces as well, a good balance that shows how healthy the Sitecore community in India is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmpy719moyaw3lewv162.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmpy719moyaw3lewv162.png" alt="SUGCON India 2023 Photo Collage" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just want to finish off by saying that of course trips like this aren’t always about work though, we always try to make sure that we get out and see some of the places we visit and India is no different. On this trip, we made the journey down to see the Taj Mahal after the event had finished, and it truly is an amazing site to see. Really all of the descriptions of it you hear just cannot do it justice, and it was great to experience it with the awesome team we had on-site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpwmqgkr432sqpj8rwt6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpwmqgkr432sqpj8rwt6.jpg" alt="Sitecore team photo at the Taj Mahal" width="800" height="1199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, whether it’s the always friendly people, the amazing effort from the organisers &amp;amp; speakers, the food, the noise or the general sights you see around the city – India is one of my favourite places to visit and certainly one of my favourite SUGCON events.&lt;/p&gt;

&lt;p&gt;Here’s looking forward to doing it all again in 2024!&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>community</category>
      <category>events</category>
    </item>
    <item>
      <title>Migrating the XM Cloud Introduction Repo to a new Nuget feed.</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Thu, 27 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sitecore/migrating-the-xm-cloud-introduction-repo-to-a-new-nuget-feed-1cag</link>
      <guid>https://dev.to/sitecore/migrating-the-xm-cloud-introduction-repo-to-a-new-nuget-feed-1cag</guid>
      <description>&lt;p&gt;Today I had to go through the process of migrating the XM Cloud Introduction repository to a new Nuget feed. This was required as the old feed was no longer available, and we needed to move to a new one on short notice. This post will cover the steps I needed to complete to migrate the solution to the new feed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Machine Tidy Up
&lt;/h2&gt;

&lt;p&gt;Now for anyone who hasn't run a Sitecore site before you can most likely skip this step. However, for anyone who has you should tidy up any references to the old feed that have been configured on your machine. In my case, this was the PowerShell Repository used to restore the &lt;code&gt;SitecoreDockerTools&lt;/code&gt; module used by this, and other Sitecore repositories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove PS Repository
&lt;/h3&gt;

&lt;p&gt;The first thing to check is whether you have the old Sitecore Feed registered as a PowerShell Repository, you can do this by running the following command &lt;code&gt;Get-PSRepository&lt;/code&gt; and checking where there is a record named &lt;code&gt;SitecoreGallery&lt;/code&gt;. If you have one registered, then you can remove it by running &lt;code&gt;Unregister-PSRepository -Name SitecoreGallery&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove PS Modules
&lt;/h3&gt;

&lt;p&gt;Next, I tidied up any previous versions of the &lt;code&gt;SitecoreDockerTools&lt;/code&gt; module installed from the old feed. You can test whether you have any versions of that module installed by running the &lt;code&gt;Get-Module -ListAvailable&lt;/code&gt; and look for any named &lt;code&gt;SitecoreDockerTools&lt;/code&gt;. If you have those installed, you can quickly remove all installed versions of that package by running &lt;code&gt;Uninstall-Module -Name SitecoreDockerTools -AllVersions&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update the Repository
&lt;/h2&gt;

&lt;p&gt;So now we’ve tidied our developer machine, we can update the repository to reference the new feed. This involved making two changes, an update to the &lt;code&gt;init.ps1&lt;/code&gt; script used to initialise the repository, and then an update to the &lt;code&gt;nuget.config&lt;/code&gt; to define the new location for the NuGet packages in use by the solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating the init.ps1 script
&lt;/h3&gt;

&lt;p&gt;The first thing the script does is install the &lt;code&gt;SitecoreDockerTools&lt;/code&gt; PowerShell module, so we need to update the location that it is installed from, in our case, we needed to use v2 of the Nuget feed to get it to work, so we needed to change it to &lt;code&gt;https://nuget.sitecore.com/resources/v2/&lt;/code&gt;. After making this change the init script ran successfully and installed the module from the new feed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating the nuget.config
&lt;/h3&gt;

&lt;p&gt;The final change we need to make is to update the &lt;code&gt;nuget.config&lt;/code&gt; file in the root of the repository that controls where custom NuGet packages are installed from. We had a couple of older references in there that we removed and condensed down to the single new feed reference. This resulted in us having the following line in our config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;add key="Sitecore" value="https://nuget.sitecore.com/resources/v3/index.json" /&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Updating the XM Cloud Introduction repository to the new feed location was straight forward in the end. I would recommend any developers who have been running existing Sitecore solutions before follow the tidy-up steps at the start to ensure they remove any legacy references they have to the old feed. You can see the changes we had to make in the following &lt;a href="https://github.com/Sitecore/XM-Cloud-Introduction/pull/270/commits/2a20e2b69486c128bda055e0564d7cc736820dc1" rel="noopener noreferrer"&gt;commit&lt;/a&gt;. There may be other changes that you will need to complete to bring your codebase in line, but hopefully, this will help to get you started with what tasks are required for you.&lt;/p&gt;

</description>
      <category>nuget</category>
      <category>sitecore</category>
      <category>xmcloud</category>
    </item>
    <item>
      <title>Sitecore Search - Filtering vs Faceting</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Tue, 25 Jul 2023 23:28:45 +0000</pubDate>
      <link>https://dev.to/sitecore/sitecore-search-filtering-vs-faceting-o32</link>
      <guid>https://dev.to/sitecore/sitecore-search-filtering-vs-faceting-o32</guid>
      <description>&lt;p&gt;The latest video in my series on #Sitecore #Search was published this week, discussing Filtering vs Faceting.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/wxEdfNRFMvY"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Sitecore Search – Configuring your Domain</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Mon, 10 Jul 2023 00:51:26 +0000</pubDate>
      <link>https://dev.to/sitecore/sitecore-search-configuring-your-domain-3p7c</link>
      <guid>https://dev.to/sitecore/sitecore-search-configuring-your-domain-3p7c</guid>
      <description>&lt;p&gt;The second video in my series on #Sitecore #Search was published last week, showing how you can do the initial domain configuration&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/6HlhXygfnU0"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>sitecore</category>
      <category>search</category>
    </item>
    <item>
      <title>Introducing the Sitecore Discover JavaScript SDK - Part 2 Components</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Thu, 11 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sitecore/introducing-the-sitecore-discover-javascript-sdk-part-2-components-58ch</link>
      <guid>https://dev.to/sitecore/introducing-the-sitecore-discover-javascript-sdk-part-2-components-58ch</guid>
      <description>&lt;h2&gt;
  
  
  Introducing the Sitecore Discover JavaScript SDK - Part 2 Components
&lt;/h2&gt;

&lt;p&gt;This post is the second in a two-part blog series, introducing a brand-new JavaScript SDK for Sitecore Discover. You can read the first part &lt;a href="https://dev.to/blog/introducing-the-sitecore-discover-javascript-sdk-part-1-events"&gt;here&lt;/a&gt;. In this second part, we'll dive into the component model provided by the SDK and show the different ways you can leverage Discover data in your React application. This blog is the accompaniment for the YouTube video highlighting the same features. You can watch the video below:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/hNze4QQwu30"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Components to a Page
&lt;/h2&gt;

&lt;p&gt;There are three different ways to add a component in to your React application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static components&lt;/strong&gt; : Created in the CEC (Customer Engagement Console) and dropped into the page by a developer. This is developer-centric and means the developer specifies that a specific widget will always appear in a specific area in the DOM. The merchandiser can configure the widget afterwards, but they cannot change it out for a different one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic widgets&lt;/strong&gt; : The developer leverages a &lt;code&gt;widget&lt;/code&gt; tag, similar to a placeholder in XM Cloud, allowing the merchandiser to dynamically insert widgets configured and created in the CEC. This means the developer can specify an area in the DOM, and the merchandiser can add and remove widgets from that area without the developer's involvement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global components&lt;/strong&gt; : These are components that appear on every page, such as the search bar in a header. They remain the same across different pages and routes of your site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configuring Widgets in the CEC
&lt;/h2&gt;

&lt;p&gt;Before adding any components to our application, they’ll need to be configured within the CEC. There are two different types of widgets when it comes to working with the SDK:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqppfuulvcabe2qdx36al.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqppfuulvcabe2qdx36al.png" alt="Search Wigets in the CEC" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTML widgets&lt;/strong&gt; : The layout is owned by the CEC, and the SDK can render them without any additional configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catalog widgets&lt;/strong&gt; : The layout and functionality are owned by your application. We need to tell the SDK which components in our app to use to render them by calling the &lt;code&gt;setWidgetType&lt;/code&gt; function, you can find details on that function in our &lt;a href="https://doc.sitecore.com/discover/en/developers/discover-js-sdk-for-react/setwidgettype-fucntion.html" rel="noopener noreferrer"&gt;documentation site&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An &lt;code&gt;rfk_id&lt;/code&gt; is also assigned to each of your widgets allowing you to refer to them specifically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to find a Widget examples?
&lt;/h2&gt;

&lt;p&gt;So, you might be asking where you find examples of the widgets you can create? Well you have a few supporting elements that can help you here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have the &lt;a href="https://doc.sitecore.com/discover/" rel="noopener noreferrer"&gt;documentation site&lt;/a&gt; which will show you walkthroughs of how to complete common activities with the SDK.&lt;/li&gt;
&lt;li&gt;We also have a &lt;a href="https://developers.sitecorecloud.io/discover-sdk/react/1.x-alpha/storybook/index.html?path=/docs/introduction--page" rel="noopener noreferrer"&gt;StoryBook instance&lt;/a&gt; which will give you examples of the different components included in the SDK’s UI package.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Adding Static &amp;amp; Dynamic Widgets to Our Site
&lt;/h2&gt;

&lt;p&gt;In the video, we begin by adding some widgets to our site. In the &lt;code&gt;index.tsx&lt;/code&gt; page of our Next.js application, we will use the &lt;code&gt;useEffect&lt;/code&gt; hook to tie our application's route to the specific page definition in the CEC. We will then use the &lt;code&gt;usePageWidgets&lt;/code&gt; function to get the widget data for rendering. We can then begin to replace parts of our site with dynamic or static components, as shown in the examples below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Components&lt;/strong&gt; : We can render a &lt;code&gt;div&lt;/code&gt; with a loading message, and when the loading is finished, we map through the widgets returned by the &lt;code&gt;usePageWidgets&lt;/code&gt; to render the appropriate widget component.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  {isLoading &amp;amp;&amp;amp; &amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;}
  {!isLoading &amp;amp;&amp;amp; widgets.map((w) =&amp;gt; &amp;lt;Widget rfkId={w} key={w} /&amp;gt;)}
&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Components&lt;/strong&gt; : We can use a different component tied to a specific widget in the CEC using the &lt;code&gt;widgetID&lt;/code&gt; to always render that widget at that location in the DOM.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;RecommendationGallery rfkId="rfkid_92" productsToDisplay={6} /&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing Global Widgets
&lt;/h2&gt;

&lt;p&gt;In the video we replace the existing search bar in our Next.js Commerce site with a preview search from Discover, using the code samples provided in &lt;a href="https://developers.sitecorecloud.io/discover-sdk/react/1.x-alpha/storybook/index.html?path=/docs/widget-templates-preview-search--left-story" rel="noopener noreferrer"&gt;StoryBook&lt;/a&gt;. The samples there will give you a styled, working interactive React component ready to be inserted directly into your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Discover can be used as much or as little as desired in your implementations. You can use Discover for every piece of catalog data in your channels or just for individual pieces of catalog data sprinkled throughout your channels. The other fact I liked about the platform is that it is just as easy to implement Discover in an existing storefront as it is a new greenfield project.&lt;/p&gt;

&lt;p&gt;Finally, when using the JavaScript SDK, be sure to take advantage of all the supporting features provided, such as Storybook, and the documentation site to help you build your app as quickly as possible.&lt;/p&gt;

</description>
      <category>sitecorediscover</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Introducing the Sitecore Discover JavaScript SDK - Part 1 Events</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Thu, 04 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sitecore/introducing-the-sitecore-discover-javascript-sdk-part-1-events-2jjl</link>
      <guid>https://dev.to/sitecore/introducing-the-sitecore-discover-javascript-sdk-part-1-events-2jjl</guid>
      <description>&lt;h2&gt;
  
  
  Introducing the Sitecore Discover JavaScript SDK - Part 1 Events
&lt;/h2&gt;

&lt;p&gt;In this two-part blog series, I'll be introducing you to a brand-new JavaScript SDK for Sitecore Discover. In this first part, we'll dive into the different implementation options for Sitecore Discover, explore the JavaScript SDK, and discuss its eventing model. This blog is the accompaniment for the YouTube video highlighting the same features. You can watch the video below:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/_3EJWTU5UtI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Options
&lt;/h2&gt;

&lt;p&gt;When working with Sitecore Discover there are three main integration options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hosted Pages:&lt;/strong&gt; Low developer effort but limited feature set; best for simple implementations where a merchandiser can configure everything from the Sitecore Discover Customer Engagement Center (CEC). Requires a reverse proxy or subdomain to serve pages directly from Discover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct API Integration:&lt;/strong&gt; High developer effort but full feature set; best for more complex requirements where developers manually call APIs to create custom commerce experiences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript SDK (our focus in this seres):&lt;/strong&gt; Moderate developer effort with full feature set; best for React-based applications and designed for a faster development process with boilerplate code and API calls automated for you. The SDK comprises two main elements, the eventing elements from the &lt;a href="https://www.npmjs.com/package/@sitecore-discover/react" rel="noopener noreferrer"&gt;React NPM package&lt;/a&gt;, and the component elements from the &lt;a href="https://www.npmjs.com/package/@sitecore-discover/ui" rel="noopener noreferrer"&gt;UI NPM package&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  JavaScript SDK Overview
&lt;/h2&gt;

&lt;p&gt;The JavaScript SDK for Sitecore Discover is a React library, making it suitable for React-based applications and frameworks like Next.js. Don't worry if you're using another JavaScript library or language, though – you can still choose from the other integration options mentioned earlier.&lt;/p&gt;

&lt;p&gt;Some key features of the SDK:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete control over catalog experience design&lt;/li&gt;
&lt;li&gt;Flexibility in distribution of responsibilities between developers and merchandisers&lt;/li&gt;
&lt;li&gt;Eventing &amp;amp; Custom Component models&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Eventing Model
&lt;/h2&gt;

&lt;p&gt;To start with, we'll focus on the Eventing Model. Eventing is crucial for collecting valuable information about user interactions on your site, such as page views, product details, and cart actions. This data is then used by Sitecore Discover's AI to provide personalized product experiences for users.&lt;/p&gt;

&lt;p&gt;Several events are pre-wired in the SDK, but others require manual wiring. The good news is that once you've integrated the SDK and wired up your events, Sitecore Discover automatically begins collecting data for use in its AI-powered recommendations.&lt;/p&gt;

&lt;p&gt;In the second part of this series, we'll explore the Component Model, which allows you to connect your event data with personalized product experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring up Events for Sitecore Discover
&lt;/h2&gt;

&lt;p&gt;To use the SDK, you'll need to wrap your application in a &lt;code&gt;WidgetProvider&lt;/code&gt;, which serves as the main entry point. After doing so you can begin to connect the events, some of which are automatically wired up by the SDK, while others require manual configuration. Here's a breakdown of which events fall into each category:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automatically Wired:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trackAppearEvent&lt;/li&gt;
&lt;li&gt;trackSearchResultsClickEvent&lt;/li&gt;
&lt;li&gt;trackSearchResultsFacetClickEvent&lt;/li&gt;
&lt;li&gt;trackRecommendationClick&lt;/li&gt;
&lt;li&gt;trackPreviewSearchClick&lt;/li&gt;
&lt;li&gt;trackPageViewEvent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Manually Wired:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trackAddToCartEvent&lt;/li&gt;
&lt;li&gt;trackOrderConfirmEvent&lt;/li&gt;
&lt;li&gt;trackPDPViewEvent&lt;/li&gt;
&lt;li&gt;trackStatusCartEvent&lt;/li&gt;
&lt;li&gt;trackUserLoginEvent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the manual events, you'll need to call the corresponding event function provided by the SDK and pass in any required event data (for example, the product SKU).&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing Event Tracking
&lt;/h2&gt;

&lt;p&gt;Below you can see a couple of examples of how to wire up the manual events, we’re going to use the Product Details Page View and Add to cart events as examples…&lt;/p&gt;

&lt;h3&gt;
  
  
  Product Detail Page View
&lt;/h3&gt;

&lt;p&gt;To wire up the Product Details Page View event you need to follow a couple of steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import the &lt;code&gt;useEffect()&lt;/code&gt; hook from React and the &lt;code&gt;trackPDPView&lt;/code&gt; function from the Discover SDK.&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;trackPDPView&lt;/code&gt; function with the product's SKU inside the &lt;code&gt;useEffect&lt;/code&gt; hook. An example of this is
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    trackPDPViewEvent(product.id)
}, [product.id])

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add-to-cart Action
&lt;/h3&gt;

&lt;p&gt;To wire up the Add to cart Action you need to follow a couple of steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import the &lt;code&gt;useRouter()&lt;/code&gt; hook from Next.js and the &lt;code&gt;trackCartEvent&lt;/code&gt; function from the SDK.&lt;/li&gt;
&lt;li&gt;Modify the function responsible for handling the add-to-cart action in your application by calling the &lt;code&gt;trackCartEvent()&lt;/code&gt; function with the product's SKU, price, and quantity after the original add-to-cart code executes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { asPath } = useRouter()
const eventModel: ProductEventModel[] = [
    {
        sku: product.id,
        quantity: 1,
        price: product.price.value,
    },
]
trackAddToCartEvent(eventModel, asPath)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By wiring these events, you'll start collecting valuable user interaction data that Sitecore Discover can use to generate personalized product recommendations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That brings us to the end of part one of this series. Be sure to check out part two where we'll look into the component model, and how you can use the event data we've collected to create contextual product interactions in your storefront. Thanks for reading!&lt;/p&gt;

</description>
      <category>sitecorediscover</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Upgrading the XM Cloud Introduction repository to Docker Compose v2</title>
      <dc:creator>Rob Earlam</dc:creator>
      <pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sitecore/upgrading-the-xm-cloud-introduction-repository-to-docker-compose-v2-4c0i</link>
      <guid>https://dev.to/sitecore/upgrading-the-xm-cloud-introduction-repository-to-docker-compose-v2-4c0i</guid>
      <description>&lt;p&gt;In case you haven’t heard, Docker has slowly been pushing people to migrate the latest version of Docker Compose, which is &lt;code&gt;v2&lt;/code&gt;. This has culminated in the end of life for &lt;code&gt;v1&lt;/code&gt;, which means that the functionality will be removed from all Docker Desktop versions as of Jun 2023.&lt;/p&gt;

&lt;p&gt;Our team at Sitecore is responsible for the &lt;a href="https://github.com/Sitecore/XM-Cloud-Introduction/" rel="noopener noreferrer"&gt;XM Cloud Introduction&lt;/a&gt; project, which currently uses Docker Compose for its local developer experience, so we needed to update to the latest version to ensure we could continue to work in this way. This post will cover the steps we needed to complete to migrate the solution to &lt;code&gt;v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Overall, the process was fairly simple, with most of the time being taken up by testing. In the end, it boiled down to a couple of tasks that I needed to complete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating our YAML definitions.&lt;/li&gt;
&lt;li&gt;Updated our PowerShell scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also used this as an opportunity to tidy up a few things with the docker-related files to clean up a few warnings that were being thrown after we move to &lt;code&gt;v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I’ll talk through the different changes we needed to make below, but you can see the pull request that contained the changes that were required &lt;a href="https://github.com/Sitecore/XM-Cloud-Introduction/pull/253" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating the YAML definitions
&lt;/h2&gt;

&lt;p&gt;The first thing we needed to do was to remove the top-level &lt;code&gt;version&lt;/code&gt; parameter from our main &lt;code&gt;docker-compose.yml&lt;/code&gt; file as it is no longer required when running &lt;code&gt;v2&lt;/code&gt;. After completing this we then needed to update how we were scaling some of our containers. We use containers to perform build actions, but they aren’t actually used at runtime, previously this was achieved by using a &lt;code&gt;scale&lt;/code&gt; parameter like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service-name:
    scale: 0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This syntax is incorrect when running Docker Compose v2 through, and now you should use the &lt;code&gt;deploy.replicas&lt;/code&gt; property instead, so this involved changing all instances of this to the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service-name:
    deploy:
      replicas: 0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final change we needed to make was to one of our EntryPoint values, the previous version used the following value for the EntryPoint of the CM container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entrypoint: powershell -Command "&amp;amp; C:\tools\entrypoints\iis\Development.ps1"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When attempting to use that with &lt;code&gt;v2&lt;/code&gt; though, the container failed to start as the backslashes were being stripped out. The simple fix for this was to double escape those slashes, so the new version looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entrypoint: powershell -Command "&amp;amp; C:\\tools\\entrypoints\\iis\\Development.ps1"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those were all of the changes I needed to make to our docker-compose yaml definitions, now there are other changes that have been implemented by this forced migration but they didn’t affect our solution. You can read about the full set of changes on the &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;docker site&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating the PowerShell scripts
&lt;/h2&gt;

&lt;p&gt;Once we had our yml definitions updated the last thing we needed to complete to have compatibility was to update our PowerShell scripts used to run the solution locally. The only change here was to update how the docker compose commands were issued. We have a few different ways that our solution can be run, but they all executed the containers using a command similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We had to change this slightly to remove the hyphen from the &lt;code&gt;docker-compose&lt;/code&gt; command, forcing anyone running the repo to be executing it using the v2 format, so the above command became&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up -d

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final tidy up
&lt;/h2&gt;

&lt;p&gt;After changing to run the solution using &lt;code&gt;v2&lt;/code&gt; I noticed it was throwing some extra warnings about unpopulated environment variables. After looking into it, these variables were no longer actually used in our solution, so this proved to be a good time to tidy those up as well. The final task was to update the &lt;code&gt;README&lt;/code&gt; for the repository to state that it was now using Docker Compose v2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Overall, migrating to Docker Compose v2 was fairly straightforward for our solution and didn’t involve too many changes, though it may be more complex for you depending on which v1 features you’re leveraging.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>dockercompose</category>
      <category>sitecore</category>
      <category>xmcloud</category>
    </item>
  </channel>
</rss>
