Creating CMS components
This guide will show you how you could approach adding new components to your Alokai & CMS setup. The described steps will also come in handy while editing the existing components.
Creating a frontend component
In this section, you're going to create a basic frontend Picture component that displays an image and its caption. The content for the component will be dynamic and delivered by a CMS.
Code examples in this guide refer to the /apps/storefront-unified-nextjs directory of your Next Storefront.
1
Create a component
Create a new picture.tsx
file with the following content:
import { PropsWithStyle } from '@storefront-ui/react';
import { AgnosticCmsImage } from '@vsf-enterprise/cms-components-utils';
import classNames from 'classnames';
import { PropsWithChildren, ReactNode } from 'react';
export interface PictureProps extends PropsWithStyle, PropsWithChildren {
caption: ReactNode;
image?: AgnosticCmsImage;
}
export default function Picture({ children, caption = children, className, image, ...rest }: PictureProps) {
const { alt, desktop, mobile } = image ?? {};
return (
<figure className={classNames('flex flex-col items-center', className)} {...rest}>
{image && (
<picture>
{mobile && <source media="(max-width: 768px)" srcSet={mobile} />}
{desktop && <img alt={alt} className="rounded-md" src={desktop} />}
</picture>
)}
{caption && <figcaption className="text-center">{caption}</figcaption>}
</figure>
);
}
2
Register the component
If you are using our Builder.io
integration, you have to register the Custom Component in the schemas.tsx
file:
import { RegisteredComponent } from '@builder.io/sdk-react';
import Picture from '@/components/cms/page/picture';
export const customComponents: RegisteredComponent[] = [
// ... other components schemas
{
component: Picture,
defaultChildren: [
{
'@type': '@builder.io/sdk:Element',
component: {
name: 'Editorial',
options: {
content: 'Image caption',
},
},
},
],
image: 'https://alokai.com/favicon.svg',
inputs: [
{
...baseImageInput,
name: 'image',
required: true,
},
],
name: 'Picture',
},
];
If you are using our other integrations, import the component in the render-cms-content.tsx
wrapper:
import type { ComponentType } from 'react';
import Picture from '@/components/cms/page/picture';
const components: Record<string, CmsComponent> = {
// ... other components
Picture, };
Creating a CMS component
The process of creating a structure for a custom component differs in every CMS. Select your platform from the tabs below and follow the associated guide.
In this section, you're going to create a new, custom Content Type in Amplience. It will act as a scaffolding for entries which will be rendered by your new frontend component. Remember that by default you'll be equipped with couple predefined Alokai components (content models/types).
Read more about creating Content Types in the Amplience documentation.
1
Create Content Type
Open up your Amplience Dynamic Content panel, navigate to the Development dropdown and choose Content Type schemas
. Once a popup appears on the screen, choose "code from scratch".
In the following screen, give your schema an id
(in the URI format, e.g. https://www.vuestorefront.io/picture.json
) and set Content Type
as the validation level. Hit the Create schema
button to confirm.
A schema editor window should pop up. Now you can create your own schema based on pre-configured properties listed in add property
dropdown.
2
Add the component
field
In the schema, add the component
field of type string
. It is mandatory for all Content Types which act as components (e.g. Banner, Hero). Its value should represent the name of the frontend component which will be used to render it.
Use the const
property to hardcode that value so that content editors do not have to type it manually every time they create a new Picture
entry.
{
"properties": {
"component": {
"title": "Component",
"type": "string",
"const": "Picture"
}
}
}
3
Add image
field
You can add any field you want, for our Picture Content Type we will need a image
field.
{
"properties": {
"image": {
"type": "object",
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/image-link"
}
]
}
}
}
If you want to make the field localizable, it has to be wrapped in the localized-value
. For instance the localized image would look as follows:
{
"properties": {
"image": {
"allOf":[
{
"$ref":"http://bigcontent.io/cms/schema/v1/core#/definitions/localized-value"
}
],
"properties": {
"values": {
"items": {
"properties": {
"value": {
"title": "Image",
"allOf": [
{ "$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/image-link" }
]
}
}
}
}
}
},
}
}
You can read more about the localization in the Amplience docs. We recommend also to analyze the schema for the Alokai's content types which we provide out of the box for you. You can find them in apps/storefront-middleware/sf-modules/cms-amplience/content-type-schemas/schemas
directory.
4
Add caption
content link field
To make the caption flexible, we can set a caption as Editorial
Content Type, which will allow you to use rich text features. Create the caption
field of type content-link
. As the only possible type to be chosen pick the https://www.vuestorefront.io/editorial.json
schema which allows you to add rich text.
{
"properties": {
"caption": {
"type": "object",
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content-link"
},
{
"properties": {
"contentType": {
"enum": ["https://www.vuestorefront.io/editorial.json"]
}
}
}
]
}
}
}
It is worth to mention that you can share different kind of references between schemas as described here.
5
Make the component stylable
Additionally, you can make your component stylable by adding another field of type Content link
to it. Name it styles
and let it only accept schema of the styles (https://www.alokai.com/styles_partial.json
).
{
"properties": {
"styles": {
"type": "array",
"items": {
"type": "object",
"allOf": [
{
"$ref": "https://www.alokai.com/styles_partial.json#/definitions/styles"
}
]
}
}
}
}
styles
field has to be of type array
to allow setting multiple styles based on media queries.
Once done, save your Picture Content Type schema. Now it should look like this:
{
"$id": "https://www.vuestorefront.io/picture.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content"
}
],
"title": "Picture",
"description": "Picture Content Type schema",
"type": "object",
"properties": {
"component": {
"const": "Picture",
"title": "Component",
"type": "string"
},
"image": {
"type": "object",
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/image-link"
}
]
},
"caption": {
"type": "object",
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content-link"
},
{
"properties": {
"contentType": {
"enum": ["https://www.vuestorefront.io/editorial.json"]
}
}
}
]
},
"styles": {
"items": {
"allOf": [
{
"$ref": "https://www.vuestorefront.io/styles_partial.json#/definitions/styles"
}
],
"type": "object"
},
"type": "array"
}
}
}
6
Register schema
In order to use your schema, it needs to be registered, so click on the Save and register as content type
option from Save
dropdown in upper right corner of the screen.
In the following screen set the Content type label
to Picture
and set associated repository to Content
. Optionally you can also add the icon and card for better recognition of the Content Type for final users.
7
Add Visualization
To be able to preview the Picture Content Type, go to the Visualizations tab and create a new visualization. Our module provides a /amplience-visualization
Storefront route which allows you to preview a single component in isolation. We can use this page to set up the Localhost
visualization. To to identify the component, make sure that the tokens are passed as query params, so the Visualization URL should look like this http://localhost:3000/amplience-visualization?hubName={{hub.name}}&contentItemId={{content.sys.id}}&deliveryKey={{delivery.key}}&snapshotId={{snapshot.id}}&vseDomain={{vse.domain}}&locales={{locales}}
.
Once done, click the Save
button to confirm.
You can read more about the Amplience visualizations in the official documentation.
Register the new component in the Page
To be able to use the new Picture
component in the Page
Content Type, you need to include it in the componentsAboveFold
and componentsBelowFold
fields.
Go to Development > Content Type schemas and search for the Page Content Type schema (https://www.vuestorefront.io/page.json). Open it in the editor and scroll down to the properties
section. Include the ID
of your Picture component in both componentsAboveFold
and componentsBelowFold
.
{
"properties": {
"componentsAboveFold": {
"items": {
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content-link"
},
{
"properties": {
"contentType": {
"enum": [
"https://www.vuestorefront.io/picture.json" ]
}
}
}
]
}
},
"componentsBelowFold": {
"items": {
"allOf": [
{
"$ref": "http://bigcontent.io/cms/schema/v1/core#/definitions/content-link"
},
{
"properties": {
"contentType": {
"enum": [
"https://www.vuestorefront.io/picture.json" ]
}
}
}
]
}
}
}
}
As a last step, click the blue dropdown arrow in the top-right corner and choose Save and sync Content Type
option from the list.
8
Create a new entry
Now you can create a new entry based on the Picture
Content Type. Go to the Content
tab and click the Create content
button. Choose the Picture
Content Type from the list and fill in the fields with the desired values. Once done, click the Save
button to confirm. After that, the visualization of the new entry should appear on the right side of the screen.
Read also
Congratulations! You've just created your first CMS component. Now it's time you added it to a page that can be rendered by your Storefront. Follow the guide on Creating CMS pages to see how it's done or read our other guides.