By admin • August 8, 2024
As more organizations move towards headless architecture, Sitecore XM Cloud paired with Next.js offers an excellent combination for building modern, scalable websites. One of the key benefits of Sitecore XM Cloud is its ability to dynamically manage content while Next.js provides fast rendering, client-side routing, and flexibility.
In this tutorial, we’ll walk through an example of how to create reusable and dynamic card components in Sitecore XM Cloud using Next.js. We will explore different variations of the same card component: a default card, a static card, and a card with an image.
Prerequisites
To follow along, you need the following:
- A Sitecore XM Cloud instance with JSS setup.
- A Next.js application connected to the Sitecore XM Cloud instance.
Step 1: Define the Card Component
First, let’s define a base card component in React. This component will receive fields
and params
as props, which represent the content data (fields) and the rendering parameters (params) from Sitecore.
Here’s a cleaned-up version of the card component:
import React from 'react';
import { Text, Field, RichText, Image as JssImage, Link as JssLink, ImageField, LinkField } from '@sitecore-jss/sitecore-jss-nextjs';
interface Fields {
heading: Field<string>;
body: Field<string>;
link: LinkField;
image: ImageField;
index?: number;
}
export type CardProps = {
params: { [key: string]: string };
fields: Fields;
index: number;
};
const CardDefaultComponent = (props: CardProps): JSX.Element => (
<div className={`component card ${props.params.styles}`}>
<div className="component-content">
<span className="is-empty-hint">Card</span>
</div>
</div>
);
This is a simple CardDefaultComponent
that acts as a fallback when no data is available. It can be used when fields are missing or in the process of building a card variant.
Step 2: Create the Default Card Variant
In this step, we’ll create a default card variant. The card will render the heading and body from the provided Sitecore fields.
export const Default = (props: CardProps): JSX.Element => {
const id = props.params.RenderingIdentifier;
if (props.fields) {
return (
<div className={`component card ${props.params.styles}`} id={id ? id : undefined}>
<div className="article-wrapper">
<article>
<div className="article-body">
<h3>
<Text field={props.fields.heading} />
</h3>
<RichText field={props.fields.body} />
</div>
</article>
</div>
</div>
);
}
return <CardDefaultComponent {...props} />;
};
In this default card, we are displaying:
- The
heading
as an H3 element. - The
body
as rich text (using Sitecore’sRichText
component).
Step 3: Create the Static Card Variant
The static card variant will have a structured layout with a header, body, and footer. This variant is useful for cards with a more predefined and fixed structure.
export const Static = (props: CardProps): JSX.Element => {
const id = props.params.RenderingIdentifier;
if (props.fields) {
return (
<div className={`component card ${props.params.styles}`} id={id ? id : undefined}>
<div className="card-header">
<Text field={props.fields.heading} />
</div>
<div className="card-body">
<h5 className="card-title">
<RichText field={props.fields.body} />
</h5>
<div className="card-text">
<RichText field={props.fields.body} />
</div>
</div>
<div className="card-footer">Contact number:</div>
</div>
);
}
return <CardDefaultComponent {...props} />;
};
This variant adds a bit more structure by:
- Displaying a
card-header
with the heading. - Displaying a
card-body
with the title and body content. - Adding a
card-footer
for additional information.
Step 4: Create the Card with Image Variant
This variant introduces an image, making it useful for cards that require a visual element along with the text content.
export const CardWithImage = (props: CardProps): JSX.Element => {
const id = props.params.RenderingIdentifier;
if (props.fields) {
return (
<div className={`component card ${props.params.styles}`} id={id ? id : undefined}>
<div className="article-wrapper">
<article>
<figure>
<JssImage field={props.fields.image} />
</figure>
<div className="article-body">
<h3>
<Text field={props.fields.heading} />
</h3>
<RichText field={props.fields.body} />
<JssLink field={props.fields.link} className="read-more">
Read more <span className="sr-only">about <Text field={props.fields.heading} /></span>
<svg xmlns="http://www.w3.org/2000/svg" className="icon" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" />
</svg>
</JssLink>
</div>
</article>
</div>
</div>
);
}
return <CardDefaultComponent {...props} />;
};
Here we:
- Add a
<figure>
to display the image usingJssImage
from Sitecore. - Include a link (
JssLink
) to allow users to navigate to more detailed content. - Use an SVG icon to enhance the link visually.
Step 5: Use the Card Components in the Next.js Application
Once you’ve created these variants, you can now use them within your Next.js application. Sitecore’s JSS platform will allow you to switch between these card components dynamically based on the rendering parameters or content structure defined in Sitecore.
You can map the card component variants to Sitecore renderings and configure them from the Experience Editor. This flexibility enables you to control how each card should appear, giving marketers the ability to swap between card layouts or content effortlessly.
Live demo: https://nona-local.vercel.app/ND-Test-Page