Search documentation

Search documentation

Content

Content Types

Define reusable schemas, fields, validation rules, and delivery contracts.

Define the shape of independent content#

A content type is a tenant-level schema for records that editors manage independently. Create one for an Article, Product, Author, FAQ, Location, or site-wide settings record.

Each entry created from the type belongs to a website and a language. The type itself is shared by the tenant, which keeps a model consistent across websites when that is what your organization needs.

Pick Collection or Single#

KindUse it whenExample
CollectionEditors need many entries of the same shapearticle, product, author
SingleThere should be one entry per website and languagesite_settings, footer_content

Contoprix enforces the Single rule when an entry is created: one active entry for that content type, website, and language. Choose Collection for anything that will have a list or detail route.

Plan before adding fields#

Ask one simple question: what can an editor change without asking a developer? The answer should become a field. Do not put a temporary visual preference in a general-purpose content type when it only belongs to one page block.

For example:

NeedBest model choice
A reusable Article recordContent type
A hero layout on a pageComponent type
An Article's authorRelation to an Author entry
An image selected from the libraryMedia/Image field
Several editorially ordered feature rowsRepeater or component field

Worked example: Article#

Create a Collection content type with:

SettingRecommended value
NameArticle
Codearticle
Draft supportOn
Version supportOn
LocalizationOn only when articles will exist in more than the default language

Then add these fields:

NameCodeField typeRequiredWhy
TitletitleTextYesMain headline
SlugslugSlugYesStable delivery lookup and route value
SummarysummaryText AreaNoCard and search description
BodybodyRich TextNoLong-form copy
Hero imageheroImageImageNoMedia-library asset
AuthorauthorRelationNoReusable Author entry

The slug field has special value: Contoprix reads a field with the exact code slug and uses it as the entry's delivery slug. Slugs are normalized to lowercase without leading/trailing slashes and must be unique for the same website, content type, and language.

Use field types that match the meaning#

Contoprix has many field types. Start with the type that represents the content meaning, not the one that seems fastest to render today.

Content you needGood field typeAvoid
Short label or headlineTextRich text for a one-line label
Multi-line plain copyText AreaA long text value crammed into Text
Editor-authored formatted bodyRich Text or MarkdownRendering untrusted HTML yourself
URL-safe identifierSlugAsking editors to manually keep a Text field URL-safe
One or several choicesSelect, Multi Select, Radio, CheckboxFree text when values must be consistent
Numeric amount or scoreNumber, Decimal, Currency, RatingText followed by frontend parsing
Asset from the media libraryImage, File, Gallery, Media, Video, AudioCopying an asset URL into Text
Another CMS recordRelation or Multi RelationRepeating an author or product name in text

Use Group, Object, and Repeater when a set of fields belongs together. Use a Component field when the nested structure should reuse a particular component schema. Use a Dynamic Zone when editors may choose among a deliberately limited set of component types.

Name and code fields deliberately#

| Property | Who sees it | Example | Change policy | | --- | --- | --- | | Name | Editors | Hero image | Can be improved for clarity | | Code | SDK, generated types, frontend mappers | heroImage | Treat as stable API contract |

Codes are unique within the same parent field level. Use a consistent convention such as lower camel case (heroImage) or snake case (hero_image) and keep it consistent across a project.

Warning

Changing a field code does not magically update application code. Add a replacement field, support both values during migration, update entries, and remove the old field only after no frontend code reads it.

Required, optional, and validation rules#

Mark a field required only when an entry cannot be useful without it. A title is usually required; a hero image often is not. For every optional field, define the frontend behavior before you publish the model:

An intentional optional image state
{article.heroImage ? (
  <img src={article.heroImage.url} alt={article.heroImage.alt ?? ""} />
) : null}

Use validation for length, numeric bounds, and patterns where content rules truly need them. Make editor-facing descriptions specific, for example: “Use 140 characters or fewer for card layouts.”

See the model in delivery#

After creating an Article and publishing an entry, the SDK response looks like this:

Article delivery data
const entry = await client.content.getBySlug("article", "hello-contoprix");

const article = entry.data as {
  title?: string;
  slug?: string;
  summary?: string;
};

console.log(article.title);

The content-type code is passed to the SDK method. Every model field is nested inside entry.data using its field code.

Test a type before scaling it#

  1. Create the type and one realistic entry.
  2. Fill required values and intentionally leave an optional value empty.
  3. Publish the entry.
  4. Fetch it from the frontend using the type code and slug.
  5. Confirm the UI handles full, sparse, and missing data safely.
  6. If your team uses the CLI, run contoprix pull, contoprix generate, and contoprix validate after the schema change.

Next, learn Component Types for reusable UI blocks or Relations to link Articles to Authors without copying data.