Model content types
Define and structure CMS content types in code, including properties, relationships, and search behavior, and synchronize them to Optimizely CMS.
Model content types for Optimizely CMS using the Optimizely JavaScript SDK. You define content types in code, configure their properties, relationships, and search behavior, and then synchronize them to the CMS using the CLI.
Use this approach to keep your content model versioned, reusable, and aligned with your application code.
Prerequisites
- You have installed the Optimizely JavaScript SDK.
- You have configured the Optimizely CMS CLI and connected it to your CMS instance.
- Your project uses a supported JavaScript or TypeScript setup (for example, Next.js).
1. Define a content type
Create a file in your components directory to define a content type. The following example defines an Article page type.
import { contentType } from '@optimizely/cms-sdk';
export const ArticleContentType = contentType({
key: 'Article',
baseType: '_page',
properties: {
heading: {
type: 'string',
displayName: 'Article Heading',
group: 'content',
indexingType: 'searchable',
},
body: {
type: 'richText',
displayName: 'Article Body',
group: 'content',
},
},
});This example demonstrates a basic page (_page) content type with two common property types:
- string – Use for short, unformatted text such as titles or labels.
- richText – Use for formatted content that supports rich text editing, such as article bodies.
These property types form the foundation of most content models.
Property configuration
Each property supports a set of configuration options that control how it appears in the CMS editor, how it is validated, and how it is indexed for search.
Property types
The type field defines the data type of a property. Supported types include:
string– Simple text.richText– Formatted content (Slate.js format).boolean– True or false.integer– Whole numbers.float– Decimal numbers.dateTime– Date and time values.url– Simple URLs.link– Links with metadata.binary– Binary files.json– Structured JSON.content– References to other content.contentReference– References with constraints.array– Lists of values.component– Embedded components.
URL property
Use the url type to store a simple web address as a string.
properties: {
websiteUrl: {
type: 'url',
displayName: 'Website URL',
description: 'External website link',
},
}Link property
Use the link type when you need additional metadata such as link text, title, or target.
properties: {
ctaLink: {
type: 'link',
displayName: 'Call to Action Link',
description: 'Link with title and target options',
},
}Use url for simple storage. Use link when you need full anchor tag behavior.
Date and time properties
Use the dateTime type to store dates or timestamps. You can optionally enforce minimum and maximum values.
properties: {
publishDate: {
type: 'dateTime',
displayName: 'Publish Date',
required: true,
},
eventStartTime: {
type: 'dateTime',
displayName: 'Event Start',
minimum: '2025-12-01T00:00:00Z',
maximum: '2025-12-31T23:59:59Z',
},
}Both minimum and maximum accept ISO 8601 date-time strings.
Array properties
Use the array type to store lists of values. Define the item type using the items field.
properties: {
tags: {
type: 'array',
items: { type: 'string' },
displayName: 'Tags',
minItems: 1,
maxItems: 10,
},
relatedArticles: {
type: 'array',
items: {
type: 'content',
allowedTypes: [ArticleContentType],
},
displayName: 'Related Articles',
},
}Array properties support:
minItems– Minimum number of itemsmaxItems– Maximum number of items- All item types except nested arrays
Component properties
Use the component type to embed a specific component (block) directly in another content type.
const HeroComponentType = contentType({
key: 'Hero',
baseType: '_component',
properties: {
title: { type: 'string' },
image: { type: 'contentReference', allowedTypes: ['_image'] },
},
});
const LandingPageType = contentType({
key: 'LandingPage',
baseType: '_page',
properties: {
hero: {
type: 'component',
contentType: HeroComponentType,
displayName: 'Hero Section',
},
},
});The contentType field specifies which component type the property allows.
Indexing types
The indexingType field controls how a property participates in search.
searchable(default) – Full-text search.queryable– Filtering and sorting only.disabled– Not indexed.
properties: {
title: {
type: 'string',
indexingType: 'searchable',
},
publishDate: {
type: 'dateTime',
indexingType: 'queryable',
},
internalNotes: {
type: 'string',
indexingType: 'disabled',
},
}
Content relationships
Use allowedTypes and restrictedTypes to control which content types a reference property can select.
const BlogPageContentType = contentType({
key: 'BlogPage',
baseType: '_page',
properties: {
featuredArticle: {
type: 'content',
allowedTypes: [ArticleContentType],
displayName: 'Featured Article',
},
relatedContent: {
type: 'content',
restrictedTypes: ['_folder'],
displayName: 'Related Content',
},
},
});Supported values include:
Specific content types
- Base types (
_page,_component). _selffor self-referencing.- to allow all types.
Container rules with mayContainTypes
mayContainTypesUse mayContainTypes to define which content types a container can hold.
const BlogPageContentType = contentType({
key: 'BlogPage',
baseType: '_page',
mayContainTypes: [
ArticleContentType,
'_page',
'_self',
],
});This applies to _page, _experience, and _folder base types and helps enforce structured content hierarchies.
2. Sync content types to the CMS
After defining your content types, push them to the CMS using the CLI.
npx @optimizely/cms-cli@latest config push optimizely.config.mjsThe CMS creates or updates the corresponding content types based on your configuration.
Next steps
You can now create content in the CMS using the modeled content types and fetch it through the Optimizely APIs or SDKs.
Updated about 22 hours ago
