Get started with XM Cloud + Next.js locally + deploy to Vercel in a matter of minutes

Last week the Sitecore Symposium took place in Chicago after 3 years without having the in-person event, it was amazing to be back there and meet with people in person as well as the amazing community folks during the MVP summit.

One of the main announcements was the release of XM Cloud to the public, even though we already knew about the product, and had been able to test and play with it for a while now so decided to write a quick step-by-step guide to help devs getting started, get a better understanding on the development workflow, have a quick overview of the product and so on so forth.

For this demo, I’m not spinning up any local environment (Docker containers), to make it really simple, assuming we want only to tackle it from the front-end side development and we’re not deploying any customization to the XM.

About XM Cloud

Sitecore Experience Manager Cloud (XM Cloud) is a fully managed self-service deployment platform for developers and marketers to efficiently launch engaging omnichannel experiences in the Cloud using Sitecore’s headless CMS. Experience Manager Cloud bundles the latest versions of Experience Manager, the Pages editor, Sitecore Headless Experience Accelerator (SXA), Headless Services, the Sitecore Next.js SDK (and other Heads), and Experience Edge.

With an optimized cloud-based strategy, you can rapidly and cost-effectively scale to meet your customers’ needs, shorten your time-to-market, and be more adaptive as new capabilities and functionality are added to your Martech stack. Explore how the right cloud approach will help you thrive now and into the future.

Sitecore Experience Manager Cloud re-imagines Content Management and introduces a no-compromise Content Management System (CMS) that delivers developer agility through the best attributes of the headless CMS while empowering marketers through a visually rich, WYSIWYG page composition experience. With XM Cloud, our customers can deliver relevant experiences at high speed.

  • Speed: Visitors are greeted with an experience that loads lightning-fast and engages instantly
  • Relevance: Customers are recognized and welcomed back to an experience that understands their needs

The importance of your company’s growth comes with the:

  • Agility: Marketers can easily orchestrate the overall experience across digital campaigns
  • Flexibility: Developers can rapidly develop and launch new experience types with modern front-end frameworks

XM Cloud

Architecture

XM-Cloud Architectire

XM Cloud comes with a Content Management application based on Sitecore XM including known but also new editing Tools. So, you will be able to use Content Editor as well as Experience Editor. In addition to these powerful tools, XM Cloud includes Sitecore Pages to manage your content and Design Pages, and many other tools.

The content delivery is provided by publishing to Edge. That can be Sitecore Edge (configured as default) but also other edge vendors.

Edge delivers content and design information headlessly through the GraphQL endpoint and can be consumed by any head technology such as Next.js, ASP.NET core, Angular, Vue or React.

Developers and System Administrators can manage the XM Cloud instances and deploy the custom CM (Content Management) customizations using the “build and deployment services” as well as the Deploy App that provides the functionalities via UI.

For reference, please check the official documentation here.

Now let’s put our hands to work

Creating the XM Cloud project and Site

The first step of course would be to login into the XM Cloud portal and create a new project.

Create project wizard

We can now start from a template or from existing code, I’m selecting “Start from a starter template” as I want to use the XM-Cloud Foundation project.

Step 1
Step 2
Step 3 – Integration with other providers to come
Step 4
Step 5
Step 6
Deployment Logs

Time to grab a coffee and by the time you’re back most probably the project would be ready, if that’s not the case, just have a look at the logs so you get a better understanding of what is going on there.

Deploy completed in 7 minutes

Now the deployment is done and our XM Cloud instance up and running.

Pages

If we have a look at Pages, we see the defualt Sitecore homepage, but the tree looks empty. So, let’s create our first site. For that, we go to the “Sites” tab and click on “Add your first website“:

We choose for this example the “Basic Site” template:

We give it a name (mysite) and click on create website, in a few minutes, the site will be ready.

After is done, we can get back to the “Pages” tab and start playing and exploring the new editor.

Components
Responsive view (mobile)

We can now publish the site to the Edge so we can start querying the GraphQL Endpoint:

Project options

Generating the Edge access token

Now that we have the site created and published to the Experience Edge, we have to create our Edge Token so we can set up our local Next.js app and also start querying the edge GraphQL endpoint.

We need now to connect to our XM Cloud instance, for doing that we can use the Sitecore CLI:

dotnet sitecore cloud login
Device confirmation

After you get the code, then we can start using the CLI that is now connected to our XM Cloud instance. Now get the projects list and copy the project id corresponding to the recently created project.

dotnet sitecore cloud project list
Projects list
dotnet sitecore cloud environment list --project-id {project-id}
Environments list

Now that we know the environment id, we can run the script to generate the edge token. Go to the project root folder and run the following script:

.\New-EdgeToken.ps1 -EnvironmentId {environment-id}
Experience Edge Token

We’ve created now the edge token, the script is already opening the GraphQL playground so you can add the X-GQL-Token to the headers and test a query to the home item:

GrapqhQL Playground

Setup the local Next.js project

The first step is to navigate to the FE project (/../src/sxastarter) and duplicate the “.env” file, name it “env.local” that is already excluded from git, so that we avoid pushing changes to environment variables by mistake.

In the newly created .env file, we add the API key, GraphQL endpoint, and app name:

.env.local

Now we are all set to start the next.js app locally and test it. Still in the same folder (/../src/sxastarter) we ran the commands to install all dependencies and then run the app in connected mode:

npm install
npm run start:connected

Open the browser and go to http://localhost:3000

Deploy to Vercel

Option A – Manual

Now that we have the FE app up and running locally, let’s move one step further and deploy it to Vercel.

Login to Vercel, go to https://vercel.com/new, and choose the GitHub option:

We just need to set the environment variables (the same values we already used for the local app) and make sure the root directory is set to “src/sxastarter“.

Click deploy and keep checking logs to make sure everything is going as expected:

The app is now deployed to Vercel

Here we go! The site is now running and hosted in Vercel.

App hosted in Vercel

Option B – Automatic (Experimental Feature)

First, we need to enable the experimental features, click on the settings icon, in the right upper corner and tick the checkbox:

Experimental features

Then we can go to the project settings and click on “Setup Hosting”

Project details

Click on “Create a new Vercel installation” to connect our instance to Vercel:

Vercel connector
Vercel app

Select the options and accept them. Now is ready to go and deploy:

Link to Vercel

Go to Vercel and check its progress, the project is already getting deployed in Vercel!

Deployment status – Vercel
Deployment status – Vercel
Site deployed to Vercel

Done! our site is now live and hosted in Vercel, with only a few clicks, amazing!

This blog post just shows how easy is to get started with XM Cloud, a bit of an overview of what you can expect, and a development workflow from a front-end point of view. Note: For backend development, customizations, etc. I’ll be just spinning up the containers locally and/or working with the Sitecore CLI to pull/push content, more on this later.

Thanks for reading!

References

  • Check out some very useful video series from Sebastian Winter (@lovesitecore) here.

Sitecore JSS – NEXT.js – Exploring the Incremental Site Regeneration (ISR).

Next.js allows you to create or update static pages after you’ve built your site. Incremental Static Regeneration (ISR) enables developers and content editors to use static-generation on a per-page basis, without needing to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.

Static pages can be generated at runtime (on-demand) instead of at build-time with ISR. Using analytics, A/B testing, or other metrics, you are equipped with the flexibility to make your own tradeoff on build times.

Consider an e-commerce store with 100,000 products. At a realistic 50ms to statically generate each product page, the build would take almost 2 hours without ISR. With ISR, we can choose from:

Faster Builds → Generate the most popular 1,000 products at build-time. Requests made to other products will be a cache miss and statically generate on-demand: 1-minute builds.

Higher Cache Hit Rate → Generate 10,000 products at build-time, ensuring more products are cached ahead of a user’s request: 8-minute builds.

Exploring ISR

In my previous post, I’ve created a JSS-Next.js app that we deployed to Vercel. I also created a WebHook to trigger a full rebuild in Vercel (SSG). Now, I’ll explain how the ISR works in this same app.

Fetching Data and Generating Paths

Data:

ISR uses the same Next.js API to generate static pages: getStaticProps.
By specifying revalidate: 5, we inform Next.js to use ISR to update this page after it’s generated.

Check the src/pages/[[…path]].tsx file and the getStaticProps function:

Paths:

Next.js defines which pages to generate at build-time based on the paths returned by
getStaticPaths. For example, you can generate the most popular 1,000 products at build-time by returning the paths for the top 1,000 product IDs in getStaticPaths.

With this configuration, I’m telling Next.js to enable ISR and to revalidate every 5 sec. After this time period, the first user making the request will receive the old static version of the page and trigger the revalidation behind the scenes.

The Flow

  1. Next.js can define a revalidation time per-page (e.g. 5 seconds).
  2. The initial request to the page will show the cached page.
  3. The data for the page is updated in the CMS.
  4. Any requests to the page after the initial request and before the 5 seconds window will show the cached (hit) page.
  5. After the 5 second window, the next request will still show the cached (stale) page. Next.js triggers a regeneration of the page in the background.
  6. Once the page has been successfully generated, Next.js will invalidate the cache and show the updated product page. If the background regeneration fails, the old page remains unaltered.

Page Routing

Here’s a high-level overview of the routing process:

In the diagram above, you can see how the Next.js route is applied to Sitecore JSS.

The [[…path]].tsx Next.js route will catch any path and pass this information along to getStaticProps or getServerSideProps on the context object. The Page Props Factory uses the path information to construct a normalized Sitecore item path. It then makes a request to the Sitecore Layout Service REST API or Sitecore GraphQL Edge schema to fetch layout data for the item.

Demo!

So, back to our previously deployed app in Vercel, login to Sitecore Content Editor and make a change on a field. I’m updating the heading field (/sitecore/content/sitecoreverceldemo/home/Page Components/home-jss-main-ContentBlock-1) by adding “ISR Rocks!”. We save the item and refresh the page deployed on Vercel. (Don’t publish! this will trigger the webhook that is defined in the publish:end event).

After refreshing the page, I can still see the old version:

But, if I keep checking what is going on in the ngrok, I can see the requests made to the layout service:

So, after refreshing again the page, I can see the changes there!

So, it got updated without the need of rebuilding and regenerating the whole site.

That’s it! I hope this post helps to understand how the ISR works and how to start with it on your Sitecore JSS implementation.

Thanks for reading and stay tuned for more Sitecore stuff!

Deploying a Sitecore JSS-Next.js App with SSG & ISR to Vercel (from zero to live)

In this post, I’ll share the steps to get our Next.js Sitecore App deployed into Vercel on some simple steps. Vercel is the creator of Next.js and now also a Sitecore partner. To avoid a huge and extensive post, I won’t be writing about Next.js, Vercel, JSS, etc. instead, please find some useful links with references to all those at the end of the blog post.

Getting the JSS app locally

The first step is to have the Sitecore JSS-Next.js app running locally. For simplifying things, we’ll be creating it with the help of JSS CLI. Before starting, make sure you’ve Node.js installed locally.

We just get started by running the following command to install the JSS CLI (more info here):

npm install -g @sitecore-jss/sitecore-jss-cli

Now, we can start to play with the CLI, so let’s create the app:

jss create sitecoreverceldemo nextjs

We give it a name (sitecoreverceldemo) and a framework (nextjs).

Connected Mode

The first thing we need to do is to create our API key so our JSS app can communicate to our Sitecore instance. In this demo, I’m running a local Sitecore instance, but it could be also a containerized one.

So, for doing that, we login into Sitecore and go to /sitecore/system/Settings/Services/API Keys and we create a new item, give it a name, and copy the ID somewhere, this gonna be our API key moving forward.

Now, we run the following command to start setting up it:

jss setup

We just follow the wizard and set the proper values for our Sitecore instance, API Key, import service URL, etc. If all went well, then you should see something like this:

Note that you’ve to add the recently created hostname to the hosts file in windows and ISS (sitecore.vercel.demo).

We’re now ready to deploy the configs, and right after that, the items, for doing that we simply run the following commands:

jss deploy config
jss deploy items --includeContent --includeDictionary

This will run the import to Sitecore and create the sample items. We can now build the app by running:

jss build

That’s it! We can now start our JSS App in connected mode:

jss start:connected

Code Repository

We now run some Git commands to push our code to GitHub. You can find the one I’m using for this demo here.

Vercel

Now, that we are done with our JSS Next.js app, we can have fun deploying it to Vercel. The first good news here, you can go and create your free account for testing purposes 🙂

Another good thing about Vercel is that it connects to GitHub, GitLab, and Bitbucket, so it makes things really easy. So, let’s go and import our GitHub repo there:

Let’s click on import and then configure our project. (Note: skip the Teams creation step to avoid having to get a trial account).

BUT as we have our Sitecore instance locally (or running on a container) we’ve to somehow expose our localhost to the internet. For that, we can use this amazing tool: Ngrok.

As I’m using the free version, it generates random URLs, but this is enough for our demo. Don’t forget to add those to the IIS binding and hostfile (if you’re running Sitecore locally).

Back to Vercel, we have to setup some environment variables:

SITECORE_API_KEY: The Sitecore API key we created in the previous step.
SITECORE_API_HOST: The URL generated by NGRock.
JSS_EDITING_SECRET: Your secret token. The JSS_EDITING_SECRET is optional for deployments but necessary if you want to use the Experience Editor with your Next.js Vercel deployment.

In next.config.js, replace:

const publicUrl = process.env.PUBLIC_URL;

with the following:

const publicUrl = process.env.VERCEL_URL ? https://${process.env.VERCEL_URL} : process.env.PUBLIC_URL;

So, it takes the URL we defined as an environment variable in Vercel.

Now everything is set and ready to be deployed. Let’s get back to Vercel, and deploy!

You’ll need to also update the hostname in sitecore/config/sitecoreverceldemo.config.

If everything was well configured, you should be able to see the requests to the headless services while Next.js is generating the static site during the building, something like this:

Et voila! The site is now live!

The publishing webhook

We need now to trigger the deployment if the content gets changed in the CMS. For that, we create a deploy hook in Vercel:

In the settings/Git section, we choose to create a deploy hook, we give it a name and a branch (develop in this case).

Create the hook and copy the URL. Let’s create now a config patch in Sitecore that will trigger it on publush:end

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" xmlns:search="http://www.sitecore.net/xmlconfig/search/">
  <sitecore>
    <javaScriptServices>
      <publishWebHooks type="Sitecore.JavaScriptServices.AppServices.WebHooks.WebHooks, Sitecore.JavaScriptServices.AppServices">
        <hooks hint="list:AddWebHook">
          <hook type="Sitecore.JavaScriptServices.AppServices.WebHooks.WebHookDefinition, Sitecore.JavaScriptServices.AppServices">
            <name>Vercel - Publish Hook</name>
            <url>https://api.vercel.com/v1/integrations/deploy/prj_f4NcDuveH3zCP9a6pObWlaApER14/T7ATu61aej</url>
            <method>POST</method>
            <site>sitecoreverceldemo</site>
            <body></body>
          </hook>
        </hooks>
      </publishWebHooks>
    </javaScriptServices>
  </sitecore>
</configuration>
  • url: Required. The URL of the hook to be invoked.
  • method: Optional. The HTTP method for invoking webhook. Possible values are POST or GET. The default method is POST.
  • site: Optional. The sites which should trigger the webhook when published. By default, Sitecore will trigger the webhook for every published item. If you provide the site parameter, the webhook will be invoked if the published item root is an ancestor, descendant, or equal to the configured site’s root item.

Let’s test it, make a quick change in Sitecore and publish the item (heading field):

After publishing, we can see that the deploy hook got triggered in Vercel:

Refresh the site, and we can see our changes there:

In my next post I’ll explain a bit how the ISR works as it deserves specific writing about it.

That’s it! As you can see the steps to setup your CI/CD with Vercel is quite straightforward. I hope you find this post useful and helps you with the first steps of getting into Next.js and Vercel. Stay tuned for more Sitecore stuff!

References: