Building a Component with Next.js and GraphQL from Sitecore XM Cloud Edge — No JSS Required
Goal:
In this blog post, we’ll walk through how to create a simple component in Next.js that fetches data from Sitecore XM Cloud Experience Edge using GraphQL — without using any JSS libraries.
đ§Š What You’ll Need from Your Sitecore XM Cloud Instance
Before we start coding, we’ll need a few pieces of information from your Sitecore project:
1. Edge Token and GraphQL Endpoint
-
Log in to your Sitecore XM Cloud project.
-
Select your environment.
-
Go to the "Details" tab.
-
At the bottom, you’ll see Live GraphQL IDE (Experience Edge).
-
Click "Generate Delivery API Token" — this gives you the Edge API token and the GraphQL endpoint URL.
We’ll use this token later in our .env.local file.
đ ️ Project Setup: Next.js + GraphQL
1. Create a Next.js App
Run the following command to bootstrap your app:
2. Install GraphQL Client
We'll use graphql-request for making GraphQL queries.
đ Project Structure
3. Create a GraphQL Client
Inside your project’s src folder:
// src/lib/xmclient.ts
import {
GraphQLClient }
from 'graphql-request';
const endpoint = process.
env.
NEXT_PUBLIC_XM_CLOUD_GRAPHQL_ENDPOINT ||
'';
const token = process.
env.
NEXT_PUBLIC_XM_CLOUD_EDGE_TOKEN ||
'';
export const client =
new GraphQLClient(endpoint, {
headers: {
Authorization:
`Bearer ${token}`,
},
4. Add a Sitecore Link Helper
Create a
helper folder in
src, and add a file (e.g.
sitecoreHelpers.ts) to parse Sitecore’s General Link field:
// src/helper/sitecoreHelpers.ts
export function parseGeneralLink(
link: any) {
if (!link || !link.
jsonValue)
return {
href:
'',
text:
'' };
const { href, text } = link.
jsonValue;
return {
href,
text: text || href,
}
đ Environment Configuration
5. Create a .env.local File
Add the following environment variables:
NEXT_PUBLIC_XM_CLOUD_GRAPHQL_ENDPOINT=
https://edge.sitecorecloud.io/api/graphql/v1
đ§ą Build the Component: HeroSection.tsx
6. Fetch and Render Data with GraphQL
Create a new component:
// HomepageContent.tsx
'use client';
import React, { useEffect, useState } from 'react';
import { xmGraphQLClient } from '@/lib/xmclient';
import { Field } from '@/interfaces/Field';
import { Item } from '@/interfaces/Item';
import { parseSitecoreLinkField } from '@/helper/sitecoreHelper';
const HEROCOMPONENT_QUERY = `
query heropcomponnetdata {
item(path: "/sitecore/content/demo-sites/kgcdemo/Data/Heroitem", language: "en") {
fields {
name
value
}
}
}
`;
interface HeropComponentDataResponse {
item: Item;
}
const HeroSection = () => {
const [fields, setFields] = useState<Field[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
xmGraphQLClient
.request<HeropComponentDataResponse>(HEROCOMPONENT_QUERY)
.then((res) => {
setFields(res.item.fields || []);
setLoading(false);
console.log(res);
})
.catch((err: Error) => {
setError(err.message);
setLoading(false);
console.error("Error fetching data:", err.message);
});
}, []);
// Convert fields array to an object with field names as keys
const fieldsObj = React.useMemo(() => {
const obj: Record<string, string> = {};
fields.forEach(f => {
obj[f.name] = f.value;
});
return obj;
}, [fields]);
// Parse Sitecore link fields
const resumeLink = parseSitecoreLinkField(fieldsObj.ResumeApplication, 'Resume Application');
const loginViewLink = parseSitecoreLinkField(fieldsObj.LoginView, 'Login to view');
const consolidationLink = parseSitecoreLinkField(fieldsObj.ConsolidationLink, 'Apply online');
const resumeUrl = resumeLink.url;
const loginViewUrl = loginViewLink.url;
const consolidationUrl = consolidationLink.url;
if (loading) return <section>Loading...</section>;
if (error) return <section>Error: {error}</section>;
if (!fields || fields.length === 0) return <section>No data found.</section>;
return (
<section className="flex flex-col md:flex-row w-full min-h-[400px]">
{/* Left: Background image with overlay and content */}
<div
className="relative flex-1 flex items-center justify-center min-h-[400px] bg-cover bg-center"
style={{ backgroundImage: "url('/DA/banner.jpg')" }}
>
<div className="absolute inset-0 bg-black/40" />
<div className="relative z-10 p-8 md:p-16">
<div className="mb-6">
<h2 className="text-white text-xl font-bold mb-1">
Debit card <span className="text-red-500">•</span>
</h2>
<h2 className="text-white text-xl font-bold">
Credit Card <span className="text-red-500">•</span>
</h2>
</div>
<h1 className="text-white text-4xl md:text-5xl font-extrabold mb-8 leading-tight max-w-xl">
{fieldsObj.SubTitle} <span className="text-[#ff4b5c]"></span>
</h1>
<div className="flex flex-col gap-2 max-w-xs">
<a
href="#"
className="bg-teal-500 hover:bg-teal-600 text-white font-semibold py-3 rounded mb-2 text-center transition"
>
{fieldsObj.ApplyOnline}
</a>
<a href={resumeUrl} className="text-white underline text-center">
{resumeLink.text || fieldsObj.ResumeApplication}
</a>
</div>
</div>
</div>
{/* Right: Info cards */}
<div className="flex flex-col flex-shrink-0 w-full md:w-[420px]">
<div className="flex-1 bg-[#17695b] p-8 flex flex-col justify-center min-h-[200px]">
<h3 className="text-white text-2xl font-bold mb-2">{fieldsObj.PulseTitle}</h3>
<p className="text-white text-lg mb-6">{fieldsObj.PulseDescription}</p>
<a
href={loginViewUrl}
className="text-white text-right font-semibold flex items-center gap-2 hover:underline"
>
{loginViewLink.text} <span>→</span>
</a>
</div>
<div className="flex-1 bg-[#20544a] p-8 flex flex-col justify-center min-h-[200px]">
<h3 className="text-white text-2xl font-bold mb-2">{fieldsObj.ConsolidationTitle}</h3>
<p className="text-white text-lg mb-6">{fieldsObj.ConsolidationDescription}</p>
<a
href={consolidationUrl}
className="text-white text-right font-semibold flex items-center gap-2 hover:underline"
>
{consolidationLink.text} <span>→</span>
</a>
</div>
</div>
</section>
);
};
export default HeroSection;
đ Live Demo and GitHub Repository
The application is deployed on
Vercel. You can view it live here:
HomepageAbout UsCode is available on GitHub:
đ GitHub Repo
✅ Summary
In this blog post, you’ve learned how to:
-
Get data from Sitecore XM Cloud Edge using GraphQL
-
Set up a Next.js project to use the graphql-request client
-
Parse Sitecore General Link fields
-
Render that data inside a Next.JS component
All without using JSS libraries!
Comments
Post a Comment