Content Types
Define custom content types with the schema builder. Learn about all 20 field types, nested structures, and configuration options.
What Are Content Types?
Content types define the structure of your content. A content type is a named schema with a set of field definitions — think of it as a blueprint for a category of documents. For example, you might create content types for blog posts, products, team members, FAQ entries, or landing pages.
Each content type stores its field definitions as a JSON array. When you create or edit a document, R3 CMS compiles these definitions into validation rules and auto-generates the editing form.
Content Type Structure
Every content type has the following metadata:
| Property | Required | Description |
|---|---|---|
name | Yes | Unique identifier, used in API queries (e.g., blog_post) |
label | Yes | Human-readable display name (e.g., "Blog Post") |
description | No | Help text shown in the content type list |
icon | No | Icon name for the sidebar |
slugField | No | Which field to auto-generate the URL slug from |
titleField | No | Which field displays as the document title in list views |
Field Definition Schema
Each field in a content type follows this structure:
{
"name": "title",
"label": "Title",
"type": "text",
"required": true,
"description": "The main heading for this document",
"defaultValue": null
}
| Property | Required | Description |
|---|---|---|
name | Yes | API key for the field (e.g., title, featuredImage) |
label | Yes | Display name shown in the editor |
type | Yes | One of the 20 supported field types |
required | Yes | Whether the field must have a value |
description | No | Help text shown below the field in the editor |
defaultValue | No | Default value when creating a new document |
config | No | Type-specific configuration options |
Additional properties depend on the field type — see the type-specific sections below.
Field Types Reference
text
Single-line string input. Use for titles, names, short labels.
{ "name": "title", "label": "Title", "type": "text", "required": true }
textarea
Multi-line string input with auto-sizing. Use for descriptions, excerpts, plain-text content.
{ "name": "excerpt", "label": "Excerpt", "type": "textarea", "required": false }
richText
Full-featured rich text editor powered by TipTap. Stores content as TipTap JSON. Supports formatting, links, images, and embeds.
{ "name": "body", "label": "Body", "type": "richText", "required": true }
number
Integer or floating-point number input.
{ "name": "price", "label": "Price", "type": "number", "required": true }
boolean
Toggle switch for true/false values.
{ "name": "featured", "label": "Featured", "type": "boolean", "required": false, "defaultValue": false }
date
Date picker that stores an ISO date string (e.g., 2026-03-25).
{ "name": "eventDate", "label": "Event Date", "type": "date", "required": true }
datetime
Date and time picker that stores an ISO datetime string (e.g., 2026-03-25T10:00:00.000Z).
{ "name": "scheduledFor", "label": "Scheduled For", "type": "datetime", "required": false }
image
Image upload with drag-and-drop and preview. Files are stored on R2/S3. The field value is the uploaded URL.
{ "name": "featuredImage", "label": "Featured Image", "type": "image", "required": true }
file
General file upload. Files are stored on R2/S3. The field value is the uploaded URL.
{ "name": "attachment", "label": "Attachment", "type": "file", "required": false }
slug
Auto-generated URL slug from a source field. Only allows lowercase letters, numbers, and hyphens.
{ "name": "slug", "label": "Slug", "type": "slug", "sourceField": "title" }
The sourceField property specifies which field to generate the slug from (e.g., "My Blog Post" becomes my-blog-post).
select
Dropdown with predefined options.
{
"name": "status",
"label": "Priority",
"type": "select",
"required": true,
"options": [
{ "label": "Low", "value": "low" },
{ "label": "Medium", "value": "medium" },
{ "label": "High", "value": "high" }
]
}
reference
Link to another content document. Renders as an async search field in the editor.
{
"name": "category",
"label": "Category",
"type": "reference",
"referTo": ["blog_category"]
}
The referTo array specifies which content type(s) can be referenced. The stored value is the UUID of the referenced document.
array
Repeatable list of items where each item has the same fields. Supports drag-and-drop reordering.
{
"name": "features",
"label": "Features",
"type": "array",
"minItems": 1,
"maxItems": 10,
"itemFields": [
{ "name": "title", "label": "Feature Title", "type": "text", "required": true },
{ "name": "description", "label": "Feature Description", "type": "textarea", "required": true },
{ "name": "icon", "label": "Icon", "type": "text", "required": false }
]
}
object
Nested group of fields. Renders as a collapsible fieldset. Use for grouping related data like SEO metadata or address information.
{
"name": "seo",
"label": "SEO Metadata",
"type": "object",
"fields": [
{ "name": "metaTitle", "label": "Meta Title", "type": "text", "required": false },
{ "name": "metaDescription", "label": "Meta Description", "type": "textarea", "required": false },
{ "name": "ogImage", "label": "OG Image", "type": "image", "required": false }
]
}
blocks
Typed repeatable blocks where each block can have a different structure. Ideal for flexible page builders where sections have different layouts.
{
"name": "sections",
"label": "Page Sections",
"type": "blocks",
"blocks": [
{
"name": "hero",
"label": "Hero Section",
"fields": [
{ "name": "heading", "label": "Heading", "type": "text", "required": true },
{ "name": "subheading", "label": "Subheading", "type": "textarea", "required": false },
{ "name": "backgroundImage", "label": "Background Image", "type": "image", "required": true }
]
},
{
"name": "textBlock",
"label": "Text Block",
"fields": [
{ "name": "content", "label": "Content", "type": "richText", "required": true }
]
},
{
"name": "cta",
"label": "Call to Action",
"fields": [
{ "name": "heading", "label": "CTA Heading", "type": "text", "required": true },
{ "name": "buttonText", "label": "Button Text", "type": "text", "required": true },
{ "name": "buttonUrl", "label": "Button URL", "type": "url", "required": true }
]
}
]
}
Each block item stores a _type field indicating which block definition it uses.
json
Raw JSON editor for arbitrary structured data.
{ "name": "metadata", "label": "Custom Metadata", "type": "json", "required": false }
color
Color picker that stores a hex color value (e.g., #3b82f6).
{ "name": "brandColor", "label": "Brand Color", "type": "color", "required": false }
url
URL input with built-in validation.
{ "name": "website", "label": "Website", "type": "url", "required": false }
Email input with built-in validation.
{ "name": "contactEmail", "label": "Contact Email", "type": "email", "required": false }
tags
Tag input that stores an array of strings. Renders with an autocomplete UI for adding and removing tags.
{ "name": "tags", "label": "Tags", "type": "tags", "required": false }
Example Content Type Definitions
Blog Post
{
"name": "blog_post",
"label": "Blog Post",
"slugField": "title",
"titleField": "title",
"icon": "file-text",
"fields": [
{ "name": "title", "label": "Title", "type": "text", "required": true },
{ "name": "excerpt", "label": "Excerpt", "type": "textarea", "required": false },
{ "name": "body", "label": "Body", "type": "richText", "required": true },
{ "name": "featuredImage", "label": "Featured Image", "type": "image", "required": true },
{ "name": "category", "label": "Category", "type": "reference", "referTo": ["blog_category"] },
{ "name": "tags", "label": "Tags", "type": "tags" },
{
"name": "seo",
"label": "SEO",
"type": "object",
"fields": [
{ "name": "metaTitle", "label": "Meta Title", "type": "text", "required": false },
{ "name": "metaDescription", "label": "Meta Description", "type": "textarea", "required": false }
]
}
]
}
Product
{
"name": "product",
"label": "Product",
"slugField": "name",
"titleField": "name",
"icon": "shopping-bag",
"fields": [
{ "name": "name", "label": "Product Name", "type": "text", "required": true },
{ "name": "description", "label": "Description", "type": "richText", "required": true },
{ "name": "price", "label": "Price", "type": "number", "required": true },
{ "name": "image", "label": "Product Image", "type": "image", "required": true },
{ "name": "inStock", "label": "In Stock", "type": "boolean", "required": false, "defaultValue": true },
{
"name": "variants",
"label": "Variants",
"type": "array",
"itemFields": [
{ "name": "variantName", "label": "Variant Name", "type": "text", "required": true },
{ "name": "variantPrice", "label": "Variant Price", "type": "number", "required": true },
{ "name": "sku", "label": "SKU", "type": "text", "required": true }
]
}
]
}
FAQ
{
"name": "faq",
"label": "FAQ",
"slugField": "question",
"titleField": "question",
"icon": "help-circle",
"fields": [
{ "name": "question", "label": "Question", "type": "text", "required": true },
{ "name": "answer", "label": "Answer", "type": "richText", "required": true },
{ "name": "sortOrder", "label": "Sort Order", "type": "number", "required": false, "defaultValue": 0 },
{ "name": "category", "label": "Category", "type": "select", "options": [
{ "label": "General", "value": "general" },
{ "label": "Billing", "value": "billing" },
{ "label": "Technical", "value": "technical" }
]}
]
}
Landing Page (with Blocks)
{
"name": "landing_page",
"label": "Landing Page",
"slugField": "title",
"titleField": "title",
"icon": "layout",
"fields": [
{ "name": "title", "label": "Page Title", "type": "text", "required": true },
{
"name": "sections",
"label": "Page Sections",
"type": "blocks",
"blocks": [
{
"name": "hero",
"label": "Hero",
"fields": [
{ "name": "heading", "label": "Heading", "type": "text", "required": true },
{ "name": "subheading", "label": "Subheading", "type": "textarea", "required": false },
{ "name": "backgroundImage", "label": "Background", "type": "image", "required": true },
{ "name": "ctaText", "label": "CTA Text", "type": "text", "required": false },
{ "name": "ctaUrl", "label": "CTA Link", "type": "url", "required": false }
]
},
{
"name": "features",
"label": "Features Grid",
"fields": [
{ "name": "heading", "label": "Section Heading", "type": "text", "required": true },
{
"name": "items",
"label": "Feature Items",
"type": "array",
"itemFields": [
{ "name": "featureTitle", "label": "Title", "type": "text", "required": true },
{ "name": "featureDescription", "label": "Description", "type": "textarea", "required": true },
{ "name": "featureIcon", "label": "Icon", "type": "text", "required": false }
]
}
]
},
{
"name": "richContent",
"label": "Rich Text Section",
"fields": [
{ "name": "content", "label": "Content", "type": "richText", "required": true }
]
}
]
},
{
"name": "seo",
"label": "SEO Settings",
"type": "object",
"fields": [
{ "name": "metaTitle", "label": "Meta Title", "type": "text", "required": false },
{ "name": "metaDescription", "label": "Meta Description", "type": "textarea", "required": false },
{ "name": "ogImage", "label": "Social Image", "type": "image", "required": false }
]
}
]
}
Creating Content Types via API
You can also create content types programmatically. See the API Reference for full details.
curl -X POST https://cms.yourdomain.com/api/content-types \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "blog_post",
"label": "Blog Post",
"slugField": "title",
"titleField": "title",
"fields": [
{ "name": "title", "label": "Title", "type": "text", "required": true },
{ "name": "body", "label": "Body", "type": "richText", "required": true }
]
}'