XM Cloud series: Deploying to Vercel using Azure DevOps
By Derk Hudepol on 11/17/2022
Introduction
Just like with XM Cloud, Vercel also does not come with support for Azure DevOps integration out of the box. Since Vercel is a very logical choice to go together with XM Cloud, we also need a way of deploying our Sitecore JSS App to the Vercel Cloud.
In this post I will go into how we can set this up and what we need to prepare to set this up. If you are looking for information on how to connect XM Cloud with azure DevOps, I recommend you read my previous blogpost here.
What is Azure DevOps?
Azure DevOps Server is a Microsoft product that provides version control, reporting, requirements management, project management, automated builds, testing and release management capabilities.
That being said a lot of companies leverage Azure DevOps for version control based upon git whilst also leveraging the automated build and release functionalities. This is also the case for company I work at and most of our customers
What is Vercel?
Vercel (formerly known as ZEIT) is a cloud platform that enables developers to host websites and web services that deploy instantly, scale automatically, and require no supervision. Founded in 2015 by Guillermo Rauch, Vercel offers an intuitive user interface with minimal configuration for hosting static site generators such as NextJS. Vercel is also a parent company of the Next.js framework.
Architecture
our setup is going to contain the following parts:
XM Cloud - As CMS for our content and Assets
Vercel - As the hosting platform of our Next.JS JSS application, in this case based upon the sxastarter template
Azure DevOps - As our version control and release management platform

in this architecture Developers will be pushing code to Azure DevOps and Azure DevOps will then manage releases to XM Cloud and Vercel for the respective codebases. This will happen leveraging the Vercel CLI for Vercel and Sitecore CLI for XM Cloud. If you want more information on the XM Cloud approach, please read my previous blogpost here.
Preperation
Before starting the instructions on how to set this up, please make sure you have the following ready:
an XM Cloud instance with a site setup. If you are unsure on how to setup a site please refer to my previous blogpost here. (It is about local dev but instructions on the Site setup can also be used on XM Cloud)
A published site on XM Cloud: make sure you site is published: this included the site content (under
/sitecore/content)
, the templates and Media assets. otherwise Experience edge will not return any contentA Vercel account setup. You can easily create a new free account (no credit card required) on https://www.vercel.com
An Azure DevOps account setup containing a code repository with your XM Cloud code (including the NextJS application). For my guide i will assume its the sxastarter template from the Sitecorelabs (https://github.com/sitecorelabs/xmcloud-foundation-head)
Have the code pulled locally, so we can run vercel cli commands against it
Sitecore CLI installed. If you dont have that yet, please follow the instructions in my previous blogpost here.
Information that we will need for setting up the integration
Before we start we will need to make sure we have some information on hand so we can use them during the process
SITECORE_API_KEY
To get the Sitecore API key, we will first need to have the Environment Id of our XM Cloud environment. Let's walkthrough the steps we need to take to get the information
We will first need to login to XM Cloud leveraging the Sitecore CLI:
1dotnet sitecore cloud login
After logging in, we can now query XM Cloud for our projects:
1dotnet sitecore cloud project list
this will return a result like below:
1Test Project detailed information:
2Organization Name : *******
3Organization Id : **************
4Project Id : 2EeZudkrqV84KS91loMcMI
5Project name : Test
6Region : weu (West Europe)
7Created by : derk.hudepol@**************
8Created at : **************
9Last updated by : derk.hudepol@*************
10Last updated at : *********************
Grab the project id from this result and run the command below to retrieve a list of the environment associated with the project:
1dotnet sitecore cloud environment list --project-id <project-id-here>
After running the command it should return a list of results like the one below:
1Found 1 environment(s)
2Test Environment detailed information:
3Organization Id : ********************
4Organization Name : **********************
5Project Id : 2EeZudkrqV84KS91loMcMI
6Project name : Test
7Environment Id : 5R9CHQfLDONeyaIFNO3anO
8Environment Name : Test
9Environment Host : **********************
10Environment Type : nonprod
11Created by : derk.hudepol@ **********************
12Created at : **********************
13Last updated by : derk.hudepol@ **********************
14Last updated at : **********************
15Provisioning status : Complete
16Provisioning last failure message :
Grab the environment id for the next step where we will actually get the token key we need.
Now that we have the environment id we can run the New-EdgeToken.ps1
script provided in the sxastarter project. Run it with your environment id :
1.\New-EdgeToken.ps1 -EnvironmentId <environment id here>
This command will come back with the API key. Something similar like below:
1VERBOSE: GET with 0-byte payload
2VERBOSE: received -1-byte response of content type application/json; charset=utf-8
3Launching Edge GraphQL IDE
4Add { "X-GQL-Token" : "aEoxU1R4UGM3Q1F4aHpHOXBLb0RUTGsxWUIwVHZJVW9QYUNoS2RFNkZZaz18YmRydGhlcm1lYTEtYmRQzNmI=" } to the HTTP HEADERS tab at the bottom-left of the screen to write queries against your content
Extract the Base64 token string from this message and keep this for the rest of the instructions as the API key.
JSS_APP_NAME
The JSS app name is actually very easy to get. Just copy the exact name of your Site in XM Cloud and keep it for the rest of the instructions.
Setup the Vercel project and link it to your code
Lets start off with getting the tools we need to get everything setup. To do this we will need to install the vercel cli. we can do this by simply going to the root folder of our nextjs source (/src/sxastarter
). Now run the following command to install the vercel cli:
1npm i vercel -g
This will install the vercel CLI and we can start using it now. First thing we will need to do is setup a vercel project for our source code. This is easily done by running the vercel
command, this will ask you a couple of questions and you can follow te answers i provided below except for the question on scope this will need to be your own vercel account:
1Vercel CLI 28.2.2
2? Set up and deploy “C:\src\sxa-starter\src\sxastarter”? [Y/n] y
3? Which scope do you want to deploy to? dhudepol
4? Link to existing project? [y/N] n
5? What’s your project’s name? sxastarter
6? In which directory is your code located? ./
7Local settings detected in vercel.json:
8Auto-detected Project Settings (Next.js):
9- Build Command: next build
10- Development Command: next dev --port $PORT
11- Install Command: `yarn install`, `pnpm install`, or `npm install`
12- Output Directory: Next.js default
13? Want to modify these settings? [y/N] n
14🔗 Linked to dhudepol/sxastarter (created .vercel)
15🔍 Inspect: https://vercel.com/dhudepol/sxastarter/7vZK4GvJVZSBMZXwynURTDLC8o5H [2s]
16Error: Command "npm run build" exited with 1
17Error: Check your logs at https://sxastarter-ebibfy14o-dhudepol.vercel.app/_logs or run `vercel logs sxastarter-ebibfy14o-dhudepol.vercel.app`
you will see the build fail but that is ok as we will need to run a couple of additional steps to finalize configuring vercel for our next js app. We can do this by opening up vercel on the following url : https://vercel.com/<your-username-here>/<projectname here>/settings/environment-variables
. in my case that is https://vercel.com/dhudepol/sxastarter/settings/environment-variables
.
After opening it up you will see the page below:

Before we set anything up create a local .env.example
file with the following contents, replace anything between <> with your own values:
1# For development purposes, note Next.js supports a .env.local
2# file, which is already configured to be git ignored.
3# Read more about Next.js support of environment variables here:
4# https://nextjs.org/docs/basic-features/environment-variables
5
6# The public URL to use for absolute URLs, which are required when
7# the Next.js app is run within Sitecore editors.
8# This should match the `serverSideRenderingEngineApplicationUrl`
9# in your Sitecore configuration (see \sitecore\config\sxastarter.config).
10# Be sure to update these values accordingly as your public endpoint changes.
11# See https://jss.sitecore.com/docs/fundamentals/services/view-engine
12PUBLIC_URL=<vercel url here, per example: "sxastarter-gamma.vercel.app">
13
14# To secure the Sitecore editor endpoint exposed by your Next.js app
15# (`/api/editing/render` by default), a secret token is used. This (client-side)
16# value must match your server-side value (see \sitecore\config\sxastarter.config).
17# We recommend an alphanumeric value of at least 16 characters.
18JSS_EDITING_SECRET=
19
20# Your Sitecore API key is needed to build the app. Typically, the API key is
21# defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist
22# when building locally (if you've never run `jss setup`), or when building in a
23# higher environment (since `scjssconfig.json` is ignored from source control).
24# In this case, use this environment variable to provide the value at build time.
25SITECORE_API_KEY=<your Sitecore API key>
26
27# Your Sitecore API hostname is needed to build the app. Typically, the API host is
28# defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may
29# not exist when building locally (if you've never run `jss setup`), or when building
30# in a higher environment (since `scjssconfig.json` is ignored from source control).
31# In this case, use this environment variable to provide the value at build time.
32SITECORE_API_HOST=https://xmcloudcm.localhost
33
34# Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge.
35# For Sitecore XM, this is typically optional. By default, the endpoint is calculated using
36# the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`.
37GRAPH_QL_ENDPOINT=https://edge.sitecorecloud.io/api/graphql/v1
38
39# Your default app language.
40DEFAULT_LANGUAGE=en
41
42# The way in which layout and dictionary data is fetched from Sitecore
43FETCH_WITH=GraphQL
44
45# Indicates whether SSG `getStaticPaths` pre-render any pages
46# Set the environment variable DISABLE_SSG_FETCH=true
47# to enable full ISR (Incremental Static Regeneration) flow
48DISABLE_SSG_FETCH=
49
50# Sitecore JSS npm packages utilize the debug module for debug logging.
51# https://www.npmjs.com/package/debug
52# Set the DEBUG environment variable to 'sitecore-jss:*' to see all logs:
53#DEBUG=sitecore-jss:*
54# Or be selective and show for example only layout service logs:
55#DEBUG=sitecore-jss:layout
56# Or everything BUT layout service logs:
57#DEBUG=sitecore-jss:*,-sitecore-jss:layout
58
59# Your Sitecore CDP API target (specific to your data center region)
60NEXT_PUBLIC_CDP_TARGET_URL=https://api-engage-eu.sitecorecloud.io
61
62# Your Sitecore CDP client key
63NEXT_PUBLIC_CDP_CLIENT_KEY=dummyvaluefornow
64
65# Your Sitecore CDP point(s) of sale
66# Can be provided as a single value (mypoint.com) or a multi-value JSON with locales ({"en":"en.mypoint.com","fr":"fr.mypoint.com"} etc)
67NEXT_PUBLIC_CDP_POINTOFSALE=
68
69# Timeout (ms) for Sitecore CDP requests to respond within. Default is 250.
70PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT=400
71
72# Timeout (ms) for Sitecore Experience Edge requests to respond within. Default is 250.
73PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT=400
74
75JSS_APP_NAME=<your jss app name>
You can now go ahead and upload that file to Vercel. After doing that you should see the following, validate everything and click ok:

now that all environment variables are set, you can just run the vercel
command again and the build should be successful:
1vercel
2Vercel CLI 28.2.2
3🔍 Inspect: https://vercel.com/dhudepol/sxastarter/rdR8JPSW9EbuyH8GMEzDjP6uHLYq [3s]
4✅ Preview: https://bdr-whitelabel-acceptance-dhudepol.vercel.app [1m]
5📝 To deploy to production (sxastarter-gamma.vercel.app), run `vercel --prod`
Now we are ready to move to the next step: setting up Azure DevOps.
Set-up Azure DevOps release pipeline
Before we dive into Azure DevOps we will need a couple of values so that we can actually hook it up. We will go into these values and retrieve them
Vercel personal access token
We will need a vercel personal access token so we can run a deployment without actually logging into vercel interactively. To get this token it is easiest to follow the instructions at https://vercel.com/guides/how-do-i-use-a-vercel-api-access-token. Save the token you get out of following the instructions
Vercel project id
We will the vercel project id. Luckily this can be easily found in the .vercel folder that was created in the root of our sxastarter nextjs project as part of the steps we took previously. Open the folder and open the file project.json:
1{"orgId":"6z4uNuamVg1h1taNW16ijWJm","projectId":"prj_HsR75R19lTwTPxx3NXU3k84SiUSH"}
you can grab the projectid and keep it safe for the next steps
Vercel org id
We will the vercel org id. Luckily this can also be easily found in the .vercel folder that was created in the root of our sxastarter nextjs project as part of the steps we took previously. Open the folder and open the file project.json:
1{"orgId":"6z4uNuamVg1h1taNW16ijWJm","projectId":"prj_HsR75R19lTwTPxx3NXU3k84SiUSH"}
copy the orgid value and keep it safe.
Start setting everything up in Azure DevOps
Now we can head over to the pipelines page in our Azure DevOps project:

Click "new pipeline"
and then proceed with selecting the right code repo. When DevOps is offering you starter templates just choose the "starter pipeline":

Before inputting the right YAML
code lets setup the variables for the "Vercel Token","Vercel Project Id"
and "Organisation Id".
Start by clicking variable and then adding the 3 variables with their values, make sure to set them as "secret"
:

now we can add the yaml:
1# Node.js
2# Build a general Node.js project with npm.
3# Add steps that analyze code, save build artifacts, deploy, and more:
4# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript
5
6trigger:
7- develop
8
9pool:
10 vmImage: windows-latest
11
12steps:
13- task: NodeTool@0
14 inputs:
15 versionSpec: '17.x'
16 displayName: 'Install Node.js'
17- task: PowerShell@2
18 env:
19 VERCEL_TOKEN: $(Vercel Token)
20 VERCEL_PROJECT_ID: $(Vercel project id)
21 VERCEL_ORG_ID: $(vercel organisation id)
22 inputs:
23 targetType: 'inline'
24 script: |
25 # Write your PowerShell commands here.
26
27 cd "$(Build.SourcesDirectory)/src/sxastarter"
28 npm install --global vercel@canary
29 vercel pull --yes --environment=production --token=$env:VERCEL_TOKEN
30 vercel build --prod --token=$env:VERCEL_TOKEN
31 vercel deploy --prebuilt --prod --token=$env:VERCEL_TOKEN
32
33
The steps we take here are the following:
install nodejs with version 17.x
set environment variables to contain our secret variables
browse to our nextjs source folder
install the vercel CLI
Pull the vercel environment setup from vercel (for the production environment)
Build the code leveraging the vercel configuration
Deploy the prebuilt code to vercel
Now save and run your pipeline. if everything went well you will see a succesfull job:

Now if everything went well you can browse the vercel and see a live website:

Wrapping up
Allthough setting up Vercel with Azure DevOps requires significantly more work than with Github or bitbucket, it is still possible leveraging the CLI. I hope this post helped you in setting up your starter vercel release pipeline.