Sitecore Technical Workshops - Top FAQs customers asked on XM Cloud

April 25, 2024 ·

Sitecore Technical Workshops - Top FAQs customers asked on XM Cloud

Hi Readers,

I want to talk to you about interesting things which we have been doing which is "Technical Workshops" for our customers, so here goes the scenarios.

So, we have been doing multiple types of technical workshops. 

1) Training customer and their Sitecore technical team on latest and the greatest technologies like XM Cloud & Another composable stack and try enabling them for new Sitecore tech stack.

2) Customers / Potential Customers have their agenda of existing pain points, and we take a workshop on topics around them with best practices etc. little on new technologies, so they also know the future.

Basically, we prepare custom targeted presentations & demos for individual workshops, and make sure it helps them answer their questions and they get insights of where Sitecore eco systems has to offer from their versatile toolset and try to keep them up to date with it.

So, Purpose of this blog is, because in all these customer & their technical team's engagements we get lot of questions from customers around Sitecore & Composable stack and where the world is moving, and I feel all those questions are so valid and so applicable to anyone, so why not to share it so community can know and have answers too.

Some of the questions they get are below.

QUESTIONS


1) We have our own content storage and asset management system in house, where content approval etc. takes place before making it public, is it possible to keep using it and not move to another DAM like Content Hub? 
          
Answer - 
Well, the whole purpose of composable is to use "Best of the breeds", That means customers ("you") are in control to select which tools they want to use, You will get the ultimate ROI by utilizing the tools you already have, Provided it has standard eco system of APIs which can be consumed, It could be pluggable but how much efforts is needed is purely depending on the system you use, but answer is YES, You can.

2) Can I select data center of my choice? 

Answer -
Yes & No, Because XM Cloud has predefined support for existing data centers, So there are couple of choices. 

But for example, if you already have a data center location in mind and if you want to set up XM Cloud for that region, it could be possible that currently that data center does not exist.

3) In XM Cloud, what is the disaster recovery plan? Because things are controlled by Sitecore.

Answer -

Backup and Disaster Recovery All SaaS Products are designed and configured for high availability and resiliency against local outages. Sitecore runs all critical components of each of the SaaS Products in at least 2 cloud provider datacenters in separate availability zones within the selected cloud provider region. In addition, as part of its backup procedures Sitecore replicates the backup of all Customer Data to at least 1 other region (the paired cloud datacenter region). Whenever possible the paired cloud datacenter region(s) are at least 300 miles apart, but this is not always possible given that, to satisfy data residency, tax and legal enforcement requirements, the paired cloud datacenter regions must be in the same geography.

 

Sitecore will implement and update on a periodic basis its disaster recovery policies, standards, and procedures, and will maintain strict compliance with its disaster recovery policies, standards, and procedures. Sitecore will report disasters (or potential disasters) to Customer Named Contacts promptly upon identification. Sitecore will schedule and test the components of its disaster recovery plans at least twice a year. In case of a disaster, when one of the cloud datacenter regions is disrupted or inaccessible and deemed non-recoverable by the cloud service provider, Sitecore will use best efforts to achieve a Recovery Point Objective of 24 hours and a Recovery Time Objective of 3 working days recovery at the paired cloud datacenter region. Sitecore shall use reasonable commercial endeavours to restore the lost or damaged Customer Data from the latest back-up of such Customer Data maintained by Sitecore.

See below link for more information.

Sitecore SaaS Service Level Agreement (SLA) | Sitecore Legal Hub 

4) Experience Edge has limit of 50 MB, what happens we have > 50 MB data.

Answer - 

This is the size that you are storing inside a content tree and publishing to experience edge, if you have media item size more than 50 MB, then it is advisable to use Content Hub to store your contents and not inside Sitecore Media Library.

5) To enable our team for composable stack and XM CloudHow much of the training will be needed & what kind of training for different departments and what will be typical timeline for it? 

Answer -

If we talk about full XM Cloud Enablement for below departments 

1) Technical Developers for Headless Development (1 week training can bring them to speed)

2) Content Authors – 3 days of training for “Pages” and “Components” apps and normal Sitecore XM Cloud familiarization training – (2-3 days)

3) DevOps – Creating custom CI/CD, Different hosting options, Understanding XM Cloud Deploy App and things around it, Containerization etc. (1 Week)

NOTE: Above is very customer specific, and very case by case, this was for very specific questions and requirement of training they had. 

6) How about GDPR, HIPAA and other compliance requirements.

Answer -

As of May 25, 2018, the General Data Protection Regulation (GDPR) protects the rights of Europeans to access and control their personal data. This means any brand that markets to prospects in Europe needs to be able to comply with such requirements as transferring an individual’s data to them or deleting it completely upon a user’s request. At Sitecore, we’re working across our organization to ensure compliance with the GDPR and other privacy laws, and understand that our customers will want to know how they can configure Sitecore products and services in a way that will help them with their own compliance efforts.





7) What is not available on XM Cloud which is available in XP?

Answer -

Following items are removed from XM Cloud Features and modules.

Features and modules

  • XP/xConnect/xDB functionality including existing personalization rules (a new 
  • embedded personalization experience is available for XM Cloud)
  • Marketing applications, including Experience Analytics, Experience Profile, FXM, 
  • Experience Optimization, List Manager, Campaign Creator, Path Analyzer, Marketing 
  • Automation, and the Marketing Control Panel
  • Email Experience Manager (EXM)
  • SXA with MVC, and SXA Search components
  • Sitecore Forms
  • Custom search indexes
  • Identity server
  • Sitecore Publishing Service
  • Universal Tracker
  • Device detection
  • IP Geolocation
  • MVC
  • The Update Center
Roles
  • Content Delivery
  • Content Publishing
  • Forms database
  • Web database
  • Web index
  • Sitecore Identity Server
  • Device Detection
  • IP Geolocation

  • Can you tell us difference between Vercel & Netlify?


  • Is it possible to make content available or exported from one XM Cloud project to another?

8) What it takes to migrate from XP to XM Cloud?

Answer -

This is a very subjective discussion. But it depends on a case-by-case basis. Some of the factor to be considered are.

  1. Which version of Sitecore XP it is
  2. How many modules have been used.
  3. How much of the content architecture can be utilized and reused.
  4. How many processors/pipelines have been used and many more such factors.
  5. What are the existing systems and how deeply it is integrated?
  6. Are you existing system MACH Compliant?
  7. And many more questions like these. 

9) We are using existing geo-location services, is it available in XM Cloud?

Answer -

As the world is moving to headless and XM Cloud works in a headless way, now anything related to GEO IP based attributes will be driven from your front end services like vercel, netlify etc.

This will not be provided by Sitecore, Because XM Cloud will not receive the first request, but it will be front-end application which will receive so XM Cloud will never be able to determine the visitor's location.


10) We are using lot of modules like dianoga and other Sitecore modules, are those compatible with XM Cloud?

Answer -

No. The customer should look at what they are using these modules for and evaluate if they even need anything extra at this time. If the functionalities which your modules are providing are something which is must to have, you will need to think different options which are composable in approach.

So, if we take dinoga as an example, Experience Edge, included with XM Cloud, is able to act as a CDN for the images removing the need for the caching of the asset files. The use of Vercel, or Netlify, or other delivery platforms for the head usually have some form of image caching/optimizing/delivery available with them and this also can remove a major use case for having Dianoga. DAM tools also offer web optimization capabilities, if they have this available to them.

11) We have lot of content and those contents are approved contents, so how do we migrate those content from old instance to new XM Cloud?

Answer -

There are three options here

  1. Serialization - If you are using Sitecore serialization (SCS) and using .yaml files, those can still work and you can migrate all serialized things and use to in XM Cloud.
  2. RAZL - Sitecore provides Razl, which has been tested, which is a content migration tool that is also built on serialization and works with XM Cloud as well. If a customer would like a more visual way of picking and choosing which content gets moved, they can install Razl, but Razl does require a license. A customer can install Razl, connect to their existing Sitecore XM instance, and then also connect it to their XM Cloud instance. At this point, the developer will have a source and a destination and can move content using Razl. A customer or a partner can perform that function.
  3. Content Migration Tool - It only works with XM, so if you have XM, you can use XM Cloud Content Migration tool. https://developers.sitecore.com/downloads/xm-cloud
12) It is said that there is no WEB DB in XM Cloud? Then how publish works? and how all the content are stored in XM Cloud? Does that mean our existing code will break if we have a WEB DB reference?

Answer -

Very good question, It is correct, XM Cloud uses CaaS which is Experience Edge, and instead of WEB in the publishing target, you publish it to "Experience Edge" which geo replicated CDN provided by XM Cloud which comes inbuilt with XM Cloud. https://developers.sitecore.com/content-management/edge-xm

13) We know everyone is going Composable DxP? If we decouple our presentation, Currently we host everything on CD and replicate it and load balance it, but how does it work on XM Cloiud?

Answer - 

100% valid question, Here "Unlearning is as equally important as learning", With composable stack, everything is decoupled so, you write you presentation in modern javascipt frameworks like react / NextJS and host them on hosting providers like vercel / netlify etc.

Your backend i.e Sitecore will still have its hosting but that is managed inside XM Cloud only and your publish content goes to CDN i.e Experience Edge

Your front end app to draw the presentation will be hosted platform of your choice like vercel or netlify or azure, and Sitecore provides JSS SDK for NextJS using which you can read content from experience edge and use components created in NextJS to render those data.

Your presentation and content are now decoupled, in XP all were on same CD.

NOTE : All these questions are real questions came from those workshops and which customer asked.

Before ending this blog, just want to make sure i share some of the photos where our team can be seen presenting, myself, my partner in crime Varun Shringarpure & from higher leadership, you can see Hardeep Singh Bhamra supporting us in questions related to infrastructure and cloud engineering for XM Cloud, and those who are not seen in photos but are responsible to make sure our customers are getting what they want were also there with us & supporting us Arpit Shah and Shilpa Darshini 





Some fun part, I have been part of these workshops along with my friend and colleague Varun Shringarpure and without his help and load balancing, it's never possible to cover these workshops along with project work and presales work we already have, so let me share a moment capture around 4 am in the morning where we were at the airport waiting to land at one of the potential customer's location :) 



Everything should start and end with a smile :) 

I hope this blog will get you answers of some of the common questions which are being asked by customers.





Sitecore Serialization - Error connecting to /.well-known/openid-configuration: Bad Gateway

April 08, 2024 ·

Sitecore Serialization - Error connecting to /.well-known/openid-configuration: Bad Gateway

Hi Team,

Recently, I faced an issue where for the new project my Sitecore serialization started giving me following error.


Error: "Error connecting to https://sc10.dev.local/.well-known/openid-configuration: Bad Gateway"

My identity server when browsed above url was also not working and showing following.

Well, I tried seeing logs and different things, I also followed what is given on these links. 

https://sitecore.stackexchange.com/questions/34744/open-id-configuration-issue-with-sitecore-cli
https://tekkishare.azurewebsites.net/pages/sitecore-clilogin-error-badgateway
https://www.stockpick.nl/english/sitecore-cli-login-error/

But I was still getting the same error.

Solution

If you see above screenshot of my identity server, in "Troubleshooting steps" it is mentioned that "Check the system event log for error messages."

It triggered me, I opened event log of windows, and I could see following error. 


Now, i already update my .net run time version according to identity server's config file, which given on following path (also above blog link also mentioned the same step, which i performed but still it did not work)

C:\inetpub\wwwroot\sc10IdentityServer.dev.local/Sitecore.IdentityServer.Host.runtimeconfig.json


But it was showing me to download 3.1.0 which I already did, but somehow something was missing, so now what helped me was 

in the event log itself, it provides link to missing part, you just click that link, and it downloads that version, for me the link was pointing to following.


After downloading the runtime, it worked like a charm for me & serialization is working and identity server error of 502 was also gone

Sitecore XM Cloud - 5 ways to create No code web site components with XM Cloud Component Builder

March 16, 2024 ·

Sitecore XM Cloud - 5 ways to create No code web site components with XM Cloud Component Builder


Hi People,

First of all congratulations to all 2024 MVPs, Last year has been a community year where we saw lot of new MVPs and lot of new content coming from lot of people, Good learnings.

I wanted to share some articles on the real discoveries and headless implementation we did and journey we had and what all things were involved in it etc. but i will bring that later on.

Today i am going to talk about "Component Builder", Amazing tool of Sitecore XM Cloud, Last year i did lot of research and hands on to "XM Cloud Component Builder", Very powerful futuristic tooling provided by Sitecore.

At that time it was still in "Early Access" phase, but now the offering is fully available, i wanted to revisit and provide almost all the info related to it and will also show, How to create fully functional website without writing any code, yes "It is low code / no code".

Last year i presented at SUGCON-2023-India on "FeaaS - Front End As A Service" which talked on the same line, but this blog will cover all what you can do with the component builder, So many possibilities and a new ways of working

You can find the video of the SUGCON presentation on this link here 

 If you are a podcast lover, You can also see the podcast here too


You can find everything related to component builder and the what / why / how on my PPT here 

I will highly encourage to go through the PPT too, because it covers lot of research about component builder.

Let's start with what all you can do with it and possibilities are endless.

How many ways you can create Components in XM Cloud Component Builder?

There are majorly 5 possibilities in three distinct categories using which you can create components, Sitecore has not bifurcated xm cloud components in these three categories, it is just me breaking them down into these three categories for better understanding.

1) Static Components - By using elements available to be dragged & dropped onto the canvas

Static components means, very quick and dirty way to create a component, basically you just use the component builder canvas and start drawing different elements like inline or block elements ex. H1, H2 or paragraph, cards etc. and start putting contents into it, You can even copy and paste contents from existing site and it will try to adopt its styling too.

When you stage it or publish it it gets stored as azure blob as a web components, it will have its own HTML tag and everything will be wrapped under that html tag, (Read more in my PPT about all these)

In the example below, I took https://www.sugcon.events/ site as an example, if i want to quickly just create simple component out of it by using static components approach


The moment i "Stage" the component, it will be available for me to use it on pages, all these information.

2) Dynamic Components - By using external data sources and mapping them to elements, Here before creating a component, first what you do is "Create a datasource", And to do that you go to "Data Sources" tab and start adding data sources of your choice,  In below image you can see i have three types of data source created

All these three are explained below.

  • Using Static JSON and map fields with elements
Here, use case can be if you have a service which is behind the fire wall, and you can only hit it once to get the response and you only have that JSON, Or take example of sugcon speaker list, that JSON is static once speaker are locked and it will not change, so in this scenario, you can just take that JSON and paste it in the "Paste JSON" tab option while creating a data source like following 
 


  • Consuming an API which provides JSON and map the schema with elements
You can actually make a call to your REST APIs or any APIs, which returns you the JSON results, and make use of that.


  • Using GQL by reading external services
Use cases for GQL are many, any content which is out there on experience edge or edge network or anywhere which supports GQL query, you can use that to retrieve data map it with your component, in below example, I am getting featured blogs from the context item, which is returning me the JSON schema.


 
  • By using a standard Sitecore data source and use those fields to map it to elements, this being detailed one, I have a separate blog for it, I will update the link once the blog is out.
3) BYOC (Bring Your Own Code/Components)

BYOC is the way developers can Bring Their Own Code into XM Cloud Component Builder, that means if you have your react or NextJS component library already created, you can actually use them straight into Pages in XM Cloud.

This is one of the powerful feature where your existing library can be included with simple steps and you will get that ROI (Return On Investment) because your existing code will be still reusable

I have blogged in detail about how to create and use BYOC in XM Cloud, I will also link that blog here once it is published.

I hope it gives you idea about the power of component builder.

Set up leprechaun code generation with Sitecore XM Cloud Starterkit

November 07, 2023 ·

Set up leprechaun code generation with Sitecore XM Cloud Starterkit


Hi Sitecorians,

It has been amazing learning year so far and with the change in technology and shift of the focus on frontend frameworks and composable products, it has been market demand to keep learning and exploring new things.

Reasons behind this blog

Today's topic is something that was in my draft from April-May, and I always thought that there is already a good documentation out there for Leprechaun and a blog post is not needed, Until I realized that there was so many of us facing same kind of issues and same kind of problems and spending same amount of time, That is where I thought, if I could write something which can reduce that repetitive troubleshooting time, That would really help the community.

1)  In a project environment, if we get into some configuration issues, we resolve them, we make sure we are not blocked and continue, but if you think same issue, same step and same scenario will come to other people, so if we can draft it online, it will help other people

2) I was aware about point-1 but I always thought with standard leprechaun documentation, everyone will be able to get it working and hence I never drafted my learnings and issues which I run into and steps I performed to resolve them until when lot of people were asking the same question on the floor, in different team who are configuring leprechaun, or over the slack channel, and that is where I strongly thought to draft those steps and learnings and put it online for people to refer to reduce the troubleshooting time,

3) I already drafted common troubleshooting that one will need if you are working with Sitecore XM Cloud starterkit XM Cloud - SXASTARTER Kit Setting up Leprechaun Exited with Code 1 Error (daivagnananavati.blogspot.com)  around in May, But I still did not considered steps required to configure leprechaun before troubleshooting it and I always still thought, People will be able to configure it and did not find a value to write them down.

4) But I was wrong, because only troubleshooting steps are not connecting the dots, I was still replying to same questions which I was getting from the community and from team members around, that means there was still a need of step-by-step guide of configuring leprechaun, and that is where I thought, it is definitely worth putting the steps and guide in place to save many hours of work people are doing in same repetitive manner and getting stuck in same questions.

And that is the inspiration behind this blog. and I also did a webinar on it to show what is the step-by-step guide to configure leprechaun for code generation. (Video is attached at the end of this blog)

What is Leprechaun & Why we should use it? 

I believe there is a strong awareness about it from the community and the GITHUB link of Leprechaun.CLI from Ben Lipson is just great to get started and understand things around it, so I will not focus on that but will jump directly to minimum steps involved to start generating code from it.

Steps

Step -1:  Install Leprechaun

Very first step is open windows PowerShell and go to your root directory where you have .config folder (or where your dotnet manifest file), If you are using XM Cloud starter kit, you will already have .config directory in your root project, so go to the directory inside which you have .config directory and fire below command. 

    dotnet tool install --no-cache Leprechaun.Cli

After executing this command, you will see success message that it was installed successfully, like below.                 


Once, it is installed go into .config directory and open dotnet-tools.json file and verify that the file is updated with leprechaun tool entry, that means your step-1 is finished properly.

NOTE: If you see a success message like above image but still do not see the entry in dotnet-tools.json file, Make sure to correct your path, it could be you might have installed it globally and .config was created elsewhere in which you fired the command, if you have correct path, The entry will made to this file.


Step-2: Download Leprechaun.config file & CodeGen files & modify it.

Download the file from here, you will need to modify it to suite your need and your structure, I have created a sample file which you can download from my GIST here, which has all modifications which are required.

Note - Best practice is to put the leprechaun.config file on the same level as your working directory or where your Sitecore.json file and .config folder is residing, but you are not limited to it, you can put it anywhere, but in that case, you will need to make sure all path inside that file is reflecting it too.

Because the paths in leprechaun.config are always relative to $(configDirectory) (configDirectory is the full path to the directory containing the root leprechaun config file being used)


Let's discuss the modifications you will need to do.

1) Once you download the file, first thing you will need to check is the import attribute on 

     <configurations import="**\*.module.json">

This path will differ depending on where your Leprechaun.config is and where is your module.json file, the import path will vary depending on that.

In my example I am using default start kit structure, so my module files are directly under src folder.




If this path is not configured right, you will end up with one of the Issue No. 4 of Step-4 below (end of this blog I have drafted some frequent issues that might come due to misconfigurations)

2) Second thing is giving the name to the configuration tag like below 

 <configuration name="LeprechaunDemo.Base" abstract="true">

Above name attribute should exactly match with @extends attribute of leprechaun configuration instruction in your module.json file, I have drafted further details of it in Step-3 below.

If you have misconfigured this, you will end getting Issue No.-2 (Point-2 from below list of issues I have given at bottom of the blog)

3) Update the scripts and output file attributes, scripts attribute means which code generation file you want leprechaun to use, you have to specify that path, and output means where you want leprechaun to output the generated file

I am using the type of script code generator created by David Ly for which PR is already out against Lerepchaun, but you can use other types available there as well.

Here is how my configuration node look like, and I will also show you the file structure so you can relate with the paths.

<configuration name="LeprechaunDemo.Base" abstract="true">
    <codeGenerator scripts="$(configDirectory)/CodeGen/JssTypeScript.csx"
                  outputFile="$(configDirectory)\src\sxastarter\.GeneratedTypeScriptModel\$(layer).$(module).model.ts" />
</configuration>


Make sure again you enter correct path, else you might get file not found exceptions, but in above "CodeGen" is a folder in which my JssTypeScript.csx file is residing. 

Below is the file system structure look like.



Now it is time to update module.json file so that our configurations which we did can start reading them.

Step-3: Update module.json file with leprechaun node

Because leprechaun does not need live Sitecore connection to generate your model, and it only needs persisted  *.yml files, Let's put instructions in the module.json file of your choice for which you want to generate the code, it can be your typescript model, it can be model for your templates to be used in custom resolvers, choice is yours.

So, here I am interested in generating typescript model and hence I am giving configuration of leprechaun in my DataSource template module which I already have, here is a my datasource.feature.module.json look like



In above configuration, there are two major instruction that you should configure very carefully and understand.

1) @extends - This is the name attribute of the <configuration tag of leprechaun.config (will show it in a while), That means the name attribute inside <configuration tag of leprechaun.config and @extends value should match exactly for leprechaun to work, See below image



2) @name - This should match with your {Layer}/{Module} path, Meaning, in Sitecore if you have different layers like Feature / Foundation / Project and inside that you have a module, and in which all templates are residing 

So, when you run serialization, it will create those physical yml files using those paths, This Name configuration is responsible to match that, whatever the name you give, it should be valid "path" yml for serialization.

For instance, in above example in @name, if I give anything other than Feature.LeprechaunDemo, it will not work and give me error because it will not be able to find any items on that path because it only and only needs Feature.LeprechaunDemo as a name because that is where my items are in Sitecore and all yaml files which got serialized have those paths in it.



Step-4: Run Leprechaun command.

Leprechaun command can be run in two ways.

1) Running it from the command prompt.

Go to the directory where you have configured leprechaun (your $configDirectory) and fire below command.

dotnet leprechaun /c "<<Path where your leprechaun config is>>\Leprechaun.config"

If everything configured fine you will see a success message that model was generated successfully like below 



2) Include it as a part of the build process, so at the time of build it will run leprechaun.

You can create .wpp file in your project if you would like to run and generate these models as a part of the build process, it runs the same above command, configuration you will be putting is like below.

<Target Name="Leprechaun">  
   <Exec Command="dotnet leprechaun /c <<Path where your leprechaun config is>>\Leprechaun.config"/>  
</Target>


Step-5: Troubleshoot: You will come across common issues before you get it working.

I have drafted some common issues, that you might be running into when working.
With Sitecore XM Cloud Starter kit, there are below two issues which might come.

1) One of it is "Leprechaun runs fine but it does not generate any model files",
2) If you run from the build process, you might also get "Exited with Code 1" error

Solution for both above is drafted here XM Cloud - SXASTARTER Kit Setting up Leprechaun Exited with Code 1 Error (daivagnananavati.blogspot.com)  , This is because somehow in user.json file, All environments are not updated with "authority" attribute and it's endpoint, to resolve this refer above link, it has everything you need to know.

Other Common Issues Might You Run Into
1)  Missing expected 'path' attribute on 'include' node while processing: <include name="Templates" />


This is because if you have downloaded the leprechaun.config file from the GITHUB link, On the line no. 102 it is missing "Path" attribute, Giving a proper path like below. 

<include name="Templates" path="/sitecore/templates/$(layer)/$(module)" />

NOTE: You can use my GIST here directly if you want to use that file and change it, feel free to use that, it has all the modifications.

2) There is an extend inheritance loop, or a container extending a nonexitstant container name.


This is again a mismatch in the extends property in module.json and the name of the <Configuration node, make sure leprechaun.config file configuration name and @extend is matching and other string values are just fine.

3) Item data was null for the provided treenode.


This signifies that serialized data on the disk and your module.json configuration are not matching, or either it is out of data, basically that means either something was renamed in Sitecore and synced for which the leprechaun configuration in module.json file was not updated, Double check that and see those things match.

Example can be, you renamed your module name like from demo to demo1, so on physical disk when you serialize things. It will now use demo1 in the path, so leprechaun.config should also change to reflect that name instead of demo. 

4) Loaded metadata with 0 configuration (0 total templates), No modules are being found by configurations.



This is because in your leprechaun.config file the import attribute is having a wrong path and hence leprechaun is not able to find any module.json on that path, Plese check and correct the path in following node. 

<configurations import="**\*.module.json"> of leprechaun.config , this path depends on your repo structure 

Conclusion & Some Take Aways.

1) Leprechaun does not need connection with Sitecore.
2) Leprechaun.config files(s) is always relative to $(configDirectory) (configDirectory is the full path to the directory containing the root leprechaun config file being used)
3) No need to check in the generated model files, if you have set up leprechaun to run it with build, it will help you to avoid those merge conflicts in auto generated files.
4) You can have multiple leprechaun config if you would want to have a separate model generated and different code generation to be used, Example can be for my DataSource template I want to generate type script model and for my page templates i might want to generate C# models.

I did conduct a training session on these configurations, you can refer to below webinar too for further learning and understandings.







With this blog, I hope to save some troubleshooting and configuration time you might run into.

Feel free to buzz me or comment or find me on social media and buzz or connect for any kind of conversations.

Special thanks to David Ly for creating this type script code gen file and Ben Lipson for leprechaun tool.





Sitecore XM with CD bug - _hasLayout property not working in GraphQL

October 31, 2023 ·

Sitecore XM with CD bug - _hasLayout property not working in GraphQL

Hi Team,

Recently I was working on a search solution, it was simple filtration functionality and we wanted to have simple GraphQL queries so we can get items as we need.

The setup up is Sitecore XM scaled with CM and CDs (No experience edge)

So, I just wrote simple GQL and were trying to test its results, Query worked just fine, and we were satisfied but we also wanted to have a filter for only items which had some presentation details, because we only wanted to return search results which are created from certain templates and having a presentation set on them, So the search list page will link those pages to those items.

So, I just put a standard check of _hasLayout property, using which we could target only those items which have presentation details on them, like following.


By just introducing the _hasLayout property It stopped working, though this particular project was not on XM Cloud, we tried testing it on XM Cloud environment as it is a generic search GQL, and we found out that over there _hasLayout property is working just fine and returning results.

That means, we found that there is something wrong with Sitecore XM with CDs, I tried following.

1) In the QUERY VARIABLES section, I tried passing values like "true", "false", "" but nothing worked

2) Just to check I passed " " (Empty space) and it return everything without applying filter of _hasLayout

So, behavior was wired, and we easily could figure out that there is some issue with the _hasLayout property being set by the Graph QL code somewhere in the DLL

Solution

I opened up the Sitecore Support Ticket and provided the information, after initial troubleshooting, Sitecore registered this as a bug in their tracking system with bug reference number 551736

They provided us the package of two DLLs 

1) Sitecore.Service.GraphQL.dll

2) Sitecore.Services.GraphQL.EdgeSchema.dll

After putting this hot fix, Things are working, and it returned us the results just fine as we wanted.


Just for my learnings, I will be dissembling those DLLs just to see what changed and what was missing in the standard Sitecore 10.3 XM DLLs which ships OOTB, if I find something will share it for you all too.



Error in Sitecore 10.3 XM with CDs - Could not find configuration node: database/database[@id='master']

September 24, 2023 ·

Error in Sitecore 10.3 XM with CDs - Could not find configuration node: database/database[@id='master']

Hi Team,

Recently we came across two distinct scenarios with same error message. 

1) We started getting below error when we try to hit our layout service API endpoint.


If we hit end point of CM, it was working fine and when we try to hit end point of CD it was giving this error, It was clear there is something in backend expecting master DB instead of WEB DB

In first scenario my colleague Jatin also got same issue while setting up docker instance for 10.3, and my friend Akshay Barve and I had the same observation.

2) Second scenario I was having the same exception, It was another project on 10.3 XM with CD, It was one of the migration project so we were migrating from 10.2 to 10.3, Older site was not giving any error but new site the moment we hit, it was giving same exception in the log

Issue in second scenario was in site grouping there was only site and both CM and CD URLs were given in host name and had WEB db as database, so basically there was no preview site, but both of the URLs were trying to show data from a WEB db, but issue was same because it had WEB DB and some configuration was still trying to find master DB either from DLL or from Config.

So different scenarios but same behavior and pointed to a same problem.

To troubleshoot second scenario where after upgrading it started giving error, we tried following. 

1) We checked our code and tried to find if any code is using master db configuration 

2) We also tried to check if any existing new 10.3 DLLs are having any master db reference

3) We checked in whole app_config folder and tried to search <databaseName>master</databaseName> configuration

and that is where Jatin pointed the same issue we faced and changing this file in order to give CD specific role to make it work

Same patch configuration worked for all of the two scenarios. See below in green,  

Solution

We created a patch file with below configuration, it is clearly seen that without this patch file CD will was looking for <databaseName>master</databaseName> instead of a WEB DB.

<?xml version="1.0"?>

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">

  <sitecore role:require="ContentDelivery">

    <layoutService>

      <configurations>

        <config name="sxa-jss">

          <requestContext type="Sitecore.LayoutService.Configuration.DefaultRequestContext, Sitecore.LayoutService">

            <databaseName>web</databaseName>

          </requestContext>

        </config>

      </configurations>

    </layoutService>

  </sitecore>

</configuration>

Everything worked fine after this patch.

PS: This behavior is registered as a bug by Sitecore support with 578367 reference number, and they acknowledged this behavior.

Sitecore XM/XM Cloud - Exclude specific Sitecore items from prerendering Sitecore JSS

August 07, 2023 ·

Sitecore XM/XM Cloud - Exclude specific Sitecore items from prerendering Sitecore JSS

Hi Team,

Today's post will interest most of the coder and Sitecore technologist who are working in Sitecore JSS apps and want to ignore some paths from prerendering and also want to it to content manage them, so those items which you want to ignore can be in sitecore and everything will work dynamically.

I am going to talk about how to exclude specific pages from being prerendered 

Till now, I believe most of you know how to prerender pages in Sitecore JSS apps using NextJS, Using getStaticProps function, Basically it generates static version of your Sitecore page and prerender it and save it on the server disk, so the loading of the page becomes faster and site performance is improved so i will not cover that and there is a great documentation out there on Sitecore jss site https://doc.sitecore.com/xp/en/developers/hd/19/sitecore-headless-development/prerendering-methods-and-data-fetching-strategies-in-jss-next-js-apps.html 

I will cover the scenarios on "How can you exclude some pages from being prerendered" in Sitecore JSS 10.3

Why you need to exclude pages?

There can be scenarios where you do not want some pages to be generated statically, for example redirect page items, or pages which dynamically changes like after login pages, those should be kept SSR and not SSG.

Talking about the specific scenario where if i talk about redirect page items, if you prerender them, Your NextJS app will fail at build time complaining that "Error: `redirect` can not be returned from getStaticProps during prerendering", in that case you will need to make sure that those redirect items are excluded from the array of pages which "getStaticProps" uses to generate the static pages.

I have a detailed blog post on why "Error: `redirect` can not be returned from getStaticProps during prerendering" error comes even if redirect object is given in "getStaticProps" syntax on Sitecore JSS - Error: `redirect` can not be returned from getStaticProps during prerendering (daivagnananavati.blogspot.com)

Interesting enough? and sounds like a known challenge to you all? Let's get to the solutions

Ignore specific items from being prerendered

There are multiple ways to do one thing in this new world of Sitecore JSS headless and NextJS world and it depends on what version you are but I am talking about Sitecore 10.3 JSS, Because of the different directory structure 

If you read the documentation given on https://doc.sitecore.com/xmc/en/developers/xm-cloud/customize-build-time-static-paths-in-jss-next-js-apps.html you can see the it provides "excludePaths" property in which you can give an array of paths, and those will be ignored from being statically generated, Fair enough, but this will only help when you already have known the path ahead of time, what if you want to exclude items of specific template, so when content author creates item in Sitecore, Our JSS app should automatically ignore it from prerendering?

Solution

Because we know that we can use this "excludePaths" property of "GraphQLSitemapService" and if somehow we fill this property dynamic before the getStaticProps is called, and generate those paths to be ignored dynamically, it will ignore those paths

Solution is GraphQL Search query

So idea is, You write and test query which can only get item path of specific template and make sure it is called before getStaticProps and "excludePaths" property of "GraphQLSitemapService" is filled out, following is the example where i wanted to exclude redirect items and they were created from OOTB (Out of the box) JSS redirect template


query RedirectQuery(
        $rootItemId: String = "<<home item guid>>"
        $language: String = "en"
        $pageSize: Int = 1000
        $after: String
        $redirectTemplateId: String = "<<redirect item template id without {} and "-">>"
      ) {
        search(
          where: {
            AND: [
              { name: "_path", value: $rootItemId, operator: CONTAINS }
              { name: "_language", value: $language }
              { name: "_templates", value: $redirectTemplateId, operator: EQ }
            ]
          }
          first: $pageSize
          after: $after
        ) {
          total
          pageInfo {
            endCursor
            hasNext
          }
          results {
            path
          }
        }
      }

If you run above query in GraphQL editor, It will return all the path of redirect template's item under the home node.


Now, we have the paths, we just want to find a way so it can be ignored during getStaticProps process, so to do that what we will do is we update "graphql-sitemap-service.ts" file and just before fetchSSG method of "GraphQLSitemapService", we will make sure that we update the property "excludePaths" by running a loop and creating an array of all these item which we got from the GQL query, Something like below

async exec(context?: GetStaticPathsContext): Promise<StaticPath[]> {
    if (process.env.EXPORT_MODE) {
      // Disconnected Export mode
      if (process.env.JSS_MODE !== constants.JSS_MODE.DISCONNECTED) {
        return this._graphqlSitemapService.fetchExportSitemap(config.defaultLanguage);
      }
    }
    const excludedPages = await this.GetExcludedPath();
    this._graphqlSitemapService.options.excludedPaths = excludedPages;
    return this._graphqlSitemapService.fetchSSGSitemap(context?.locales || []);
  }

If you see above code has a function which is getting called "GetExcludePath", which is calling above graphQL query and just returning the path of item, and that array we are giving into "excludePaths"

Full code of "graphql-sitemap-service.ts" looks like below

import { GraphQLRequestClient, GraphQLSitemapService } from '@sitecore-jss/sitecore-jss-nextjs';
import config from 'temp/config';
import { SitemapFetcherPlugin } from '..';
import { GetStaticPathsContext } from 'next';
import { StaticPath, constants } from '@sitecore-jss/sitecore-jss-nextjs';
import { gql } from '@apollo/client';

class GraphqlSitemapServicePlugin implements SitemapFetcherPlugin {
  _graphqlSitemapService: GraphQLSitemapService;

  constructor() {
    this._graphqlSitemapService = new GraphQLSitemapService({
      endpoint: config.graphQLEndpoint,
      apiKey: config.sitecoreApiKey,
      siteName: config.jssAppName,
    });
  }

  async exec(context?: GetStaticPathsContext): Promise<StaticPath[]> {
    if (process.env.EXPORT_MODE) {
      // Disconnected Export mode
      if (process.env.JSS_MODE !== constants.JSS_MODE.DISCONNECTED) {
        return this._graphqlSitemapService.fetchExportSitemap(config.defaultLanguage);
      }
    }
    const excludedPages = await this.GetExcludedPath();
    this._graphqlSitemapService.options.excludedPaths = excludedPages;
    return this._graphqlSitemapService.fetchSSGSitemap(context?.locales || []);
  }

  async GetExcludedPath(): Promise<string[]> {
    const EXCLUDE_PAGE = gql`
      query RedirectQuery(
        $rootItemId: String = "<<home item GUID>>"
        $language: String = "en"
        $pageSize: Int = 1000
        $after: String
        $redirectTemplateId: String = "<<redirect item template id without {} and "-">>"
      ) {
        search(
          where: {
            AND: [
              { name: "_path", value: $rootItemId, operator: CONTAINS }
              { name: "_language", value: $language }
              { name: "_templates", value: $redirectTemplateId, operator: EQ }
            ]
          }
          first: $pageSize
          after: $after
        ) {
          total
          pageInfo {
            endCursor
            hasNext
          }
          results {
            path
          }
        }
      }
    `;
    const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {
      apiKey: config.sitecoreApiKey,
    });

    const result = await graphQLClient.request<any>(EXCLUDE_PAGE as any);
    const arr = result?.search?.results;

    const pages: any[] | PromiseLike<string[]> = [];
    arr?.map((item: any) => {
      // Fix for SC ticker no CS0387155
      const path = item?.path?.replace('/sitecore/content/<<tenant>>/<<site name>>/Home', '');
      pages.push(path);
    });
    return pages;
  }
}

export const graphqlSitemapServicePlugin = new GraphqlSitemapServicePlugin();


Now, this items will be excluded from prerendering, remember if you have limited items and if they are known at build time, you can also give it directly in excludePath property in array and it will ignore those paths from being prerendered. 

NOTE: In a GraphQL above, I have used "path" and not "url { path }", There is a reason to it, because there is a bug if I use url { path } which I have explained in my blog post 


I hope this will help many of you, also refer to following blog post where I faced issues and also blogged about those specifics.