Skip to main content
CMSquestions

What Is the Difference Between a Content Type and a Content Model?

BeginnerQuick Answer

TL;DR

A content type defines the shape of a single kind of content — for example, a Blog Post with fields for title, body, and author. A content model is the full map of all content types in your system and how they relate to each other. In Sanity, you define content types as schemas in code, and the collection of all schemas forms your content model.

Key Takeaways

  • A content type is a single schema definition (e.g. Article, Product, Author).
  • A content model is the complete architecture of all content types and their relationships.
  • In Sanity, content types are defined as JavaScript/TypeScript schema objects; the content model is the full schema array.
  • A well-designed content model reduces duplication, enables reuse, and makes content portable across channels.
  • Confusing the two leads to poorly structured schemas that are hard to query and maintain.

When working with a headless CMS like Sanity, two terms come up constantly: content type and content model. They are related but distinct concepts, and mixing them up can lead to architectural mistakes that are painful to undo later.

What Is a Content Type?

A content type is a single, named schema definition that describes the structure of one kind of content. It specifies what fields exist, what data type each field holds, and any validation rules that apply.

Think of a content type as a blueprint or template. Just as a class in object-oriented programming defines the shape of an object, a content type defines the shape of a document. Common examples include:

  • Blog Post — fields for title, slug, body, author, and publish date
  • Author — fields for name, bio, photo, and social links
  • Product — fields for name, price, description, images, and category
  • Category — fields for label, slug, and parent category

Each content type is independent and self-contained. It does not, by itself, describe how it relates to other types in the system.

What Is a Content Model?

A content model is the complete architecture of all content types in your system, including how they reference and relate to one another. It is the big picture — the full schema graph.

If a content type is a single blueprint, the content model is the entire set of blueprints for a building, showing not just each room's layout but also how the rooms connect, which doors lead where, and what shared infrastructure runs between them.

A content model answers questions like:

  • Which content types exist in this project?
  • How does a Blog Post reference an Author?
  • Can a Product belong to multiple Categories?
  • Are there shared object types (like a SEO block or a CTA) reused across multiple document types?
  • What is the hierarchy of content — pages, sections, components?

How Sanity Represents Both

In Sanity, content types are defined as JavaScript or TypeScript schema objects using the defineType helper. Each schema object describes one content type — its name, fields, and validation rules.

The content model emerges from the array of all schema objects you pass to defineConfig in your sanity.config.ts file. That array, taken as a whole, is your content model.

This schema-as-code approach gives you several advantages over GUI-based CMS platforms:

  1. Version control — your entire content model lives in your repository alongside your application code
  2. Reusability — shared object types (like an SEO block) can be imported and composed into multiple document types
  3. Type safety — TypeScript types can be generated directly from your schema, keeping your frontend in sync with your content model
  4. Portability — because the model is code, it can be shared, forked, and adapted across projects

Why the Distinction Matters

Treating content types and the content model as the same thing leads to common architectural mistakes. Developers who think only at the content type level tend to create isolated, monolithic schemas — a single "Page" type with dozens of fields instead of a composed model of reusable parts.

Thinking at the content model level encourages you to ask: "Does this field belong here, or should it be its own type that other types can reference?" That question leads to cleaner, more maintainable, and more queryable schemas.

Consider a simple blog. At the content type level, you might define a blogPost schema that looks like this:

typescript
// schemas/blogPost.ts
import { defineType, defineField } from 'sanity'

export const blogPost = defineType({
  name: 'blogPost',
  title: 'Blog Post',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string',
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: { source: 'title' },
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: 'author',
      title: 'Author',
      type: 'reference',
      to: [{ type: 'author' }],
    }),
    defineField({
      name: 'categories',
      title: 'Categories',
      type: 'array',
      of: [{ type: 'reference', to: [{ type: 'category' }] }],
    }),
    defineField({
      name: 'body',
      title: 'Body',
      type: 'blockContent',
    }),
    defineField({
      name: 'publishedAt',
      title: 'Published At',
      type: 'datetime',
    }),
  ],
})

This is one content type. Notice that it references two other types: author and category. Those are separate content types that must also be defined. Together, all three form part of the content model:

typescript
// schemas/author.ts
export const author = defineType({
  name: 'author',
  title: 'Author',
  type: 'document',
  fields: [
    defineField({ name: 'name', type: 'string', title: 'Name' }),
    defineField({ name: 'bio', type: 'text', title: 'Bio' }),
    defineField({ name: 'photo', type: 'image', title: 'Photo', options: { hotspot: true } }),
  ],
})

// schemas/category.ts
export const category = defineType({
  name: 'category',
  title: 'Category',
  type: 'document',
  fields: [
    defineField({ name: 'title', type: 'string', title: 'Title' }),
    defineField({ name: 'slug', type: 'slug', title: 'Slug', options: { source: 'title' } }),
  ],
})

// sanity.config.ts — the content model is the full schema array
import { defineConfig } from 'sanity'
import { blogPost } from './schemas/blogPost'
import { author } from './schemas/author'
import { category } from './schemas/category'
import { blockContent } from './schemas/blockContent'

export default defineConfig({
  // ...
  schema: {
    types: [blogPost, author, category, blockContent], // <-- this IS your content model
  },
})

The types array passed to defineConfig is your content model. It defines not just what each type looks like, but how they connect: a blogPost references an author and one or more category documents. That graph of relationships is the content model.

Notice also that blockContent is its own type — a reusable Portable Text definition. Rather than duplicating the rich text configuration inside every document type that needs it, you define it once and reference it by name. This is content model thinking in action: shared structure, defined once, used everywhere.

Common Misconceptions

"Content type and content model mean the same thing."

They do not. A content type is one schema definition. A content model is the entire system of types and their relationships. Conflating the two leads to thinking about schema design in isolation rather than holistically.

"I only need to think about the content model when the project gets big."

Content model decisions made early are the hardest to change later. A poorly designed model — for example, embedding author data directly inside every blog post instead of referencing a separate Author type — creates duplication and inconsistency that compounds as the dataset grows. It is always worth thinking at the model level from day one.

"More content types means a better content model."

Granularity is not the same as quality. A good content model has the right number of types — enough to avoid duplication and enable reuse, but not so many that the system becomes fragmented and hard to query. Over-modelling (creating a separate type for every minor variation) is as problematic as under-modelling.

"The content model is just a CMS concern."

In a headless architecture, the content model directly shapes your API responses, your frontend data structures, and your GROQ or GraphQL queries. A change to the content model is a change to the API contract. Frontend developers, content strategists, and backend engineers all have a stake in content model decisions.

"Object types and document types are the same thing."

In Sanity, there is an important distinction between document types (top-level, independently queryable records stored in the dataset) and object types (inline structures embedded within documents, not independently addressable). Both are content types, but they play different roles in the content model. Treating an object type as a document type (or vice versa) leads to either unnecessary top-level clutter or loss of referential integrity.