Here are all properties that are defined at the model level, i.e. not under a specific field.

Model Properties


  • Allowed values: page, data, object
  • Required: only for data
  • Default: inferred based on context

The type of the model. Learn more about model types.

Note the following:

  • page and data must also specify the filePath property.
  • page must specify the urlPath property.
type: page
# ... other properties


  • Allowed values: The model's name. Names should only contain alphanumeric characters or an underscore, and must start with a letter.
  • Required: Yes

The model's name is used whenever an instance of this model is stored or this model is referenced anywhere, and thus it typically should not be changed. It is recommended to use names with all initial letters capitalized, e.g. CaseStudySection.

The model name is included in all content items via their type attribute, which is automatically set by Stackbit when the content is stored. In other words, the model name is the content type.


  • Allowed values: A human readable label for the field.
  • Required: No
  • Default: If omitted, the name of the model is used, with all initial letters capitalized.

A short, descriptive name for the model that is shown to the content editor in various elements of our UI. You can freely change it without breaking any other models or content, e.g. when adding a new page or in the CMS view.


  • Allowed values: The name of an existing field in this model - whose value best describes the specific content item.
  • Required: No
  • Default: If there's a field in the model called "title", this will be default. Otherwise, "label" if such as field exists, and as a last fallback: the first field of type string that the UI encounters.

This property is used by the editor UI to make it easier to navigate between and within pages. Whenever a content item name is shown in the UI, e.g. in the CMS view, in the site navigation widget or in other places, the value of this field in that content item will be used to label the item.


This only applies to Git CMS.

Stackbit stores new pages at {pagesDir}/{filePath} and non-pages under {dataDir}/{filePath}.

Supported File Formats

New content files are formatted according to the file extension you set. Supported formats include:

  • json
    filePath: '{slug}.json'
    # => "hello-world.json"
  • md
    filePath: '{slug}.md'
    # => ""
  • toml
    filePath: '{slug}.toml'
    # => "hello-world.toml"
  • yaml
    filePath: '{slug}.yaml'
    # => "hello-world.yaml"

Using Variables

These property is meant to be dynamic, based on input from the editor, and therefore supports variable interpolation. The following are supported:

  • title: The title, manually set by the editor.
    filePath: '{title}.md'
    # => "Hello"
  • slug: The slug field, manually set by the editor.
    filePath: '{slug}.json'
    # => hello-world.json
  • moment_format: A formatted version of today's date using Moment.js formats. Note: Use date as the first argument with this option.
    filePath: "posts/{moment_format(date, 'YYYY-MM-DD')}-{slug}.yaml"
    # => posts/2022-02-22-hello-world.yaml


  • Allowed values: URL-friendly characters, with interpolation (see below)
  • Required: No
  • Default: /{slug}

The urlPath setting tells Stackbit how to build the sitemap by providing a path for all of a model's page.

Resolving Dynamic Values

Values inside curly braces are interpolated to resolve individual page properties. For example, consider the following config:

    type: page
    urlPath: '/blog/{id}'

Stackbit will retrieve all documents of the post model, and use each one's id property to build an array of paths for the sitemap — e.g. ["/blog/1", "/blog/2", "..."].

Working with File-Based Content

When working with file-based content (Git CMS), the filePath property must be set when using file-based content.

Also note the unique behavior of slug fields, which affects how URLs are built if using the slug property.

Singleton Models

For singleton models (models with only a single document), the urlPath can be hard-coded to explicitly what the path should be.

For example, a site with a single blog page might be configured like this:

    type: page
    urlPath: '/blog'


  • Allowed values: string
  • Required: false

Description of the model.

name: Post
label: Blog Post
description: Create a new blog post


  • Allowed values: A list of one or more model names
  • Required: No
  • Default: None

The model will inherit all fields in the models included in the list. This model can then define any new fields of its own (see reference below).

If this model declares a field with the same name as a field it inherited, then that field's attributes are merged: any field attributes explicitly set in this model are used. Then, inherited field attributes are used as long as they as not overridden in the model.

That means you can not only override field attributes fully, but also easily add/change specific attributes of inherited fields, e.g. setting a default for a field which better matches this model.

Here's an example for how the built-in HeroSection extends Section:

name: HeroSection
label: Hero section
  - Section
  - sectionComponent
  - name: styles
    label: Styles
  - name: settings
    label: Settings
  - name: colors
    default: colors-f
  - name: width
    default: wide
  - name: height
    default: tall
  # ...
  - type: string
    name: title
    label: Title
    default: This Is A Big Hero Headline

Note how some fields only have a name and a default, without even a type. These fields are present in the Section model - with either a different default or no default at all.


  • Allowed values: List of strings
  • Required: No
  • Default: None

This model-level attribute defines one or more groups in which the model is a member. The attribute works in tandem with the groups attribute at the field level.

When defining fields of type model or reference which point to other model names, you may wish to have a list of acceptable model names which is not hard-coded, e.g. "any section-like component is applicable for nesting here", or "any person-like component can be referenced from here".

In the above snippet from the HeroSection model, the model declares that it belongs in the "sectionComponent" group. Here is how this group name is then used for the "sections" field in the PageLayout model:

name: PageLayout
label: Page
  - type: list
    name: sections
      type: model
        - sectionComponent


  • Allowed values: List of objects, each with name and label properties (required), and an optional icon property.
  • Required: No
  • Default: None

This attribute is used by the editor UI to visually place related fields in separate groups. This has no effect on the content itself or how it is stored - it is only used to make editing content pieces with multiple fields easier. This attribute works in tandem with the group attribute for fields.

Any field that does not has an assigned group is put by the editor UI under the default group "Content" (regardless of whether any field groups were defined).

In the below snippet, two field groups are used, and then the colors field is assigned to the "styles" group.

name: Section
  - name: styles
    label: Styles
    icon: palette
  - name: settings
    label: Settings
    icon: gear
  # ...
  - type: enum
    name: colors
    group: styles
  # ...

Available icon values are listed until the icon control in our component playground.

Field groups icon component control


  • Allowed values: true/false
  • Required: No
  • Default: false

By default, the UI assumes that any page models implicitly have a content field with Markdown-formatted content. When the page is edited in the UI, this field will be available to edit under the name "Content".

Here's how it looks like in the UI when editing a blog post:

Editing page content

For pages that do not need this functionality, set hideContent: true.

For this functionality to work, define page model files to have an .md extension. When storing Markdown files, all fields except this one are stored as front matter. The content field is then the actual Markdown text below the front matter. For pages whose model declared hideContent: true, you will find only front matter in files.

Our built-in components expect this field value to be available in a property named markdown_content under the content object passed to them for rendering. For example, look for page.markdown_content in our PostLayout component.

In our themes, this property is added to relevant content objects as they're read from files. You can fully customize this behavior with your own components.


  • Allowed values: A list of objects, each defining one field.
  • Required: Yes

Field properties are covered in detail in the next chapter.

Automatic handling of index pages

The UI has special handling for index pages:

  • When a user adds a new page and sets its path it /plans/ (note the trailing slash!), the page content will be stored to the file /content/pages/plans/
  • When you navigate to this page, the UI will know to map the URL /plans/ back to /content/pages/plans/

Configuring URL paths for an API-based CMS

The slug concept is common in many CMS systems and site generators. It's a special field which is used to map the content item to a URL. The slug may be automatically generated from another field (e.g. the title) or it could be manually set. Typically, the field holding the slug is simply called slug as well.

By default, urlPath is set to '/{slug}'. This means URLs are mapped directly to the slug field in the content piece, but you can specify another field name instead.

One common need is to tweak the urlPath depending on the model type, e.g. for all content items of type Post in the CMS, setting urlPath: '/blog/{slug}'.