Example application of GenAI : converting HTML to an actual XM Cloud NextJS component
By Derk Hudepol on 1/08/2024
With GenAI becoming more and more important in our day to day live i have also been experimenting with how it can help us in XM Cloud projects. Most specifically moving old sites to XM Cloud.
In this blog post i will dive into how ChatGPT can help migrating to XM Cloud, most specifically in converting the html of the old site into a functioning XM Cloud component.
Why ChatGPT?
I chose ChatGPT because this is not achievable with Github CoPilot yet and everyone has got access to ChatGPT. With Microsoft using openAI behind their services you could also do similar interactions with the AI Studio from Microsoft.
Key assumptions when doing this
The assumptions going in for the approach i am showing in this blogpost are:
You are moving a component like for like, so no redesign
you already have the data templates setup in Sitecore , or its part of your process
You can reuse the css of the original website
If these are not true you can still take away useful points from this blog post but it will not be a 100% match.
Steps to converting HTML to Sitecore NextJS using ChatGPT
We first need to start by selecting a component we want to move. for the sake of examples i went with a component from the apple.com website:

To get started we need the html of the component. i got this by using the developer tools of chrome:
1<div data-unit-id="macbook-air-m3" data-analytics-section-engagement="name:promo-macbook-air-m3">
2 <div class="module-content">
3 <div class="unit-wrapper">
4 <a
5 class="unit-link"
6 href="/macbook-air/"
7 target="_self"
8 rel="follow"
9 data-analytics-region="learn more"
10 aria-hidden="true"
11 tabindex="-1"
12 > </a>
13 <div class="unit-copy-wrapper">
14 <h3 class="headline" aria-label="Macbook Air">MacBook Air</h3>
15 <p class="subhead">Lean. Mean. M3 machine.</p>
16 <div class="cta-links">
17 <a
18 class="button button-primary"
19 href="/macbook-air/"
20 target="_self"
21 rel="follow"
22 data-analytics-region="learn more"
23 data-analytics-title="learn more - macbook air with m3 chip"
24 aria-label="Learn more, Macbook Air with M3 chip"
25 >Learn more</a>
26 <a
27 class="button button-tertiary"
28 href="/us/shop/goto/buy_mac/macbook_air"
29 target="_self"
30 rel="follow"
31 data-analytics-region="buy"
32 data-analytics-title="buy - macbook air with m3 chip"
33 aria-label="Buy, Macbook Air with M3 chip"
34 >Buy</a>
35 </div>
36 </div>
37 <div class="unit-image-wrapper">
38 <figure class="unit-image unit-image-macbook-air-m3-promo-macbook-air-m3"></figure>
39 </div>
40 </div>
41 </div>
42</div>
43
Now that we have the code we can actually get started with ChatGPT. First we will send ChatGPT the code as a chat message without any instruction. it will respond with a explanation of the HTML

Now we need to change this into something useful. Lets take a first step by having it convert the code to NextJS, with ReactJS and hooks:
1Convert this to NextJS , keeping the following in mind:
2- All text should be replaced by a prop
3- The link should be replaced with a NextJs link and the url and text should come from a prop
4- the image should come from a prop
5- it should be in typescript, preventing the use of any as a type
ChatGPT will respond with a code result and an explanation:
1import Image from 'next/image';
2import Link from 'next/link';
3import React from 'react';
4
5interface MacBookAirPromoProps {
6 headline: string;
7 subhead: string;
8 learnMoreUrl: string;
9 learnMoreText: string;
10 buyUrl: string;
11 buyText: string;
12 imageUrl: string;
13 imageAlt: string;
14}
15
16const MacBookAirPromo: React.FC<MacBookAirPromoProps> = ({
17 headline,
18 subhead,
19 learnMoreUrl,
20 learnMoreText,
21 buyUrl,
22 buyText,
23 imageUrl,
24 imageAlt,
25}) => {
26 return (
27 <div data-unit-id="macbook-air-m3" data-analytics-section-engagement="name:promo-macbook-air-m3">
28 <div className="module-content">
29 <div className="unit-wrapper">
30 <div className="unit-copy-wrapper">
31 <h3 className="headline" aria-label={headline}>
32 {headline}
33 </h3>
34 <p className="subhead">{subhead}</p>
35 <div className="cta-links">
36 <Link href={learnMoreUrl} passHref>
37 <a
38 className="button button-primary"
39 aria-label={`Learn more, ${headline}`}
40 >
41 {learnMoreText}
42 </a>
43 </Link>
44 <Link href={buyUrl} passHref>
45 <a
46 className="button button-tertiary"
47 aria-label={`Buy, ${headline}`}
48 >
49 {buyText}
50 </a>
51 </Link>
52 </div>
53 </div>
54 <div className="unit-image-wrapper">
55 <Image
56 src={imageUrl}
57 alt={imageAlt}
58 className="unit-image"
59 layout="responsive"
60 width={800}
61 height={600}
62 />
63 </div>
64 </div>
65 </div>
66 </div>
67 );
68};
69
70export default MacBookAirPromo;
71

This is now a nice and functioning NextJS component but it is not yet an actual Sitecore XM Cloud component. luckily we can tell ChatGPT what it needs to do :
1Can you now use Sitecore JSS ( @sitecore-jss/sitecore-jss-nextjs ) and convert all props into the right Sitecore props, and make sure that it uses the right renderers
It has now actually done quite a decent job we will need to tune it further:
1import React from 'react';
2import { Field, ImageField, LinkField, TextField } from '@sitecore-jss/sitecore-jss-nextjs';
3import { Text, Link, Image } from '@sitecore-jss/sitecore-jss-nextjs';
4
5interface MacBookAirPromoProps {
6 fields: {
7 headline: TextField;
8 subhead: TextField;
9 learnMoreLink: LinkField;
10 buyLink: LinkField;
11 promoImage: ImageField;
12 };
13}
14
15const MacBookAirPromo: React.FC<MacBookAirPromoProps> = ({ fields }) => {
16 return (
17 <div data-unit-id="macbook-air-m3" data-analytics-section-engagement="name:promo-macbook-air-m3">
18 <div className="module-content">
19 <div className="unit-wrapper">
20 <div className="unit-copy-wrapper">
21 <h3 className="headline" aria-label={fields.headline.value}>
22 <Text field={fields.headline} />
23 </h3>
24 <p className="subhead">
25 <Text field={fields.subhead} />
26 </p>
27 <div className="cta-links">
28 <Link
29 field={fields.learnMoreLink}
30 className="button button-primary"
31 aria-label={`Learn more, ${fields.headline.value}`}
32 >
33 <Text field={fields.learnMoreLink?.text} />
34 </Link>
35 <Link
36 field={fields.buyLink}
37 className="button button-tertiary"
38 aria-label={`Buy, ${fields.headline.value}`}
39 >
40 <Text field={fields.buyLink?.text} />
41 </Link>
42 </div>
43 </div>
44 <div className="unit-image-wrapper">
45 <Image field={fields.promoImage} className="unit-image" />
46 </div>
47 </div>
48 </div>
49 </div>
50 );
51};
52
53export default MacBookAirPromo;
54
The issues we see are:
The buttons are having a nested text field
we are missing anything to do with the css classes for rendering params
We are missing the required "component" class
Lets see if we have these issues fixed by chatgpt:
1We need to improve a couple of things:
2- please do not nest the text inside of a link. the link renderer itself will take care of it
3- can you add params to the props and then render the params.styles in the styles of the root div
4- please add the component class to the root div
1import React from 'react';
2import { Field, ImageField, LinkField, TextField } from '@sitecore-jss/sitecore-jss-nextjs';
3import { Text, Link, Image } from '@sitecore-jss/sitecore-jss-nextjs';
4
5interface MacBookAirPromoProps {
6 fields: {
7 headline: TextField;
8 subhead: TextField;
9 learnMoreLink: LinkField;
10 buyLink: LinkField;
11 promoImage: ImageField;
12 };
13 params?: {
14 styles?: string;
15 };
16}
17
18const MacBookAirPromo: React.FC<MacBookAirPromoProps> = ({ fields, params }) => {
19 return (
20 <div
21 className={`component macbook-air-promo ${params?.styles || ''}`}
22 data-unit-id="macbook-air-m3"
23 data-analytics-section-engagement="name:promo-macbook-air-m3"
24 >
25 <div className="module-content">
26 <div className="unit-wrapper">
27 <div className="unit-copy-wrapper">
28 <h3 className="headline" aria-label={fields.headline.value}>
29 <Text field={fields.headline} />
30 </h3>
31 <p className="subhead">
32 <Text field={fields.subhead} />
33 </p>
34 <div className="cta-links">
35 <Link
36 field={fields.learnMoreLink}
37 className="button button-primary"
38 aria-label={`Learn more, ${fields.headline.value}`}
39 />
40 <Link
41 field={fields.buyLink}
42 className="button button-tertiary"
43 aria-label={`Buy, ${fields.headline.value}`}
44 />
45 </div>
46 </div>
47 <div className="unit-image-wrapper">
48 <Image field={fields.promoImage} className="unit-image" />
49 </div>
50 </div>
51 </div>
52 </div>
53 );
54};
55
56export default MacBookAirPromo;
57
You can see it now made the final changes and we now have a component that we can use in XM Cloud.
Bonus: ready made GPT
I have actually added the instruction to create a GPT out it which people can use. if you browse to the gpt .
You can now just drop the html in like we did previously, but it will now give this response:

now we need to answer it :
1The component name should be "Product Promo"
2
3i am ok with the all the field names and i would like the image to be converted
the resulting code is :
1import { FC } from 'react';
2import { Field, ImageField, LinkField, Text, Link, Image } from '@sitecore-jss/sitecore-jss-nextjs';
3
4type ProductPromoProps = {
5 params: ProductPromoParams;
6 fields: {
7 headline: Field<string>;
8 subhead: Field<string>;
9 learnMoreLink: LinkField;
10 buyLink: LinkField;
11 backgroundImage: ImageField;
12 };
13};
14
15interface ProductPromoParams {
16 [key: string]: string;
17}
18
19const ProductPromo: FC<ProductPromoProps> = ({ params, fields }) => {
20 return (
21 <div className={`product-promo ${params.styles || ''}`}>
22 <div className="module-content">
23 <div className="unit-wrapper">
24 <Link field={fields.learnMoreLink} className="unit-link" aria-hidden="true" tabIndex={-1}>
25
26 </Link>
27 <div className="unit-copy-wrapper">
28 <Text tag="h3" field={fields.headline} className="headline" />
29 <Text tag="p" field={fields.subhead} className="subhead" />
30 <div className="cta-links">
31 <Link field={fields.learnMoreLink} className="button button-primary" />
32 <Link field={fields.buyLink} className="button button-tertiary" />
33 </div>
34 </div>
35 <div className="unit-image-wrapper">
36 <Image field={fields.backgroundImage} className="unit-image" />
37 </div>
38 </div>
39 </div>
40 </div>
41 );
42};
43
44export default ProductPromo;
45
And it will also give you improvement suggestions:

Have fun trying it out!
Conclusion
As you can see , even with generic toosl like ChatGPT you are able to increase your productivity and take tedious tasks out of your daily workload. I would recommend using a more secure AI like Azure OpenAI when working on customer projects but the principles behind it stay the same, and the results are similar.