Model fields define the individual fields that make up a particular model. Model fields describe the name, and the type of the data fields, stored in the front-matter of markdown files, and in JSON/TOML/YAML files. As well as their presentation and behavior inside the editing interface of the CMS and/or Stackbit Studio.

Note: If your project is configured to work with API-based headless-CMS such as Contentful or Sanity, the model fields will be fetched from the headless-CMS. Therefore, you don't need to specify them.

Basic Example

Take the following markdown document with 3 front matter fields.

content/posts/my-post.md

---
date: "2014-09-28"
title: "Creating a New Theme"
banner_image: images/cat.png
---

This is a post about cats.

This document would have the corresponding fields in the stackbit.yaml:

models:
  posts: # this is a page model
    type: page
    label: Blog Posts
    folder: posts
    fields: # these are the fields
      - type: string # field of type: string
        name: title # name maps to the field in the front matter
        label: Title
        required: true
      - type: date # a field of type: date
        name: date 
        label: Publish Date
      - type: image # field of type: image
        name: banner_image
        label: Main blog post image

Field Naming Conventions

The following rules apply to naming fields:

  • Field names can only contain alphanumeric characters, hyphens - or underscores _
  • Field name must start with a letter
  • Field names must not start or end with a hyphen - or an underscore _

Field Properties

type

  • Allowed values: Any valid field type
  • Required: true

Example

fields:
  - type: string
    name: title

name

  • Allowed values: Field name, must be unique among other fields of the same model
  • Required: true

Field name should contain only alphanumeric characters, underscore and a hyphen [A-Za-z0-9_]. Must start with a letter. Must not end with an underscore or a hyphen.

Example

fields:
  - type: image
    name: featured_image

label

Should be short enough as some CMS's have restrictions on its length. Some CMS require label to be unique.

Example

fields:
  - type: image
    name: featured_image
    label: Featured Image

description

  • Allowed values: Short description to editors how the field is to be used
  • Required: false

Example

fields:
  - type: image
    name: featured_image
    label: Featured Image
    description: The featured image shown above the post content

required

  • Allowed values: A boolean flag indicating if the field should be required
  • Default:: false
  • Required: false

Example

fields:
  - type: string
    name: title
    required: true

default

  • Allowed values: The default value for this field that will be used when creating a new object
  • Required: false

This is not a fallback value that will be used when the field is not set or empty.

Stackbit Studio will set a field to its default value when creating new objects. In some CMSes this is only a UI editor feature, so when a user creates a new object with a hidden field from within a CMS, the default value will not be set.

Example

fields:
  - type: string
    name: title
    required: true
    default: Replace with page title

const

  • Allowed values: The constant value that should be used when the creating a new object
  • Required: false

Stackbit Studio will set a field to its constant value when creating new objects. Some CMSes do not have a concept of constant or initial fields. Therefore, when Stackbit Site Builder provisions such CMS, the "constant" field is simulated by creating a field with "default" + "required" + "readOnly" properties, or if these are not supported, a required enum field with a single option will be created, or any other combination that will ensure that when an object with a constant field is created, it will be saved with a constant value, and prevent user from setting it to anything else.

Example

Sites created with Hugo and Jekyll have a special layout field that define page's template. Assuming every model defines a page rendered by a specific template, you can define a constant layout field that will be set to a predefined value when user creates a page.

fields:
  - type: string
    name: layout
    label: Page Layout
    const: post
    required: true
    hidden: true

hidden

  • Allowed values: A boolean flag indicating if the field should be hidden from the editor
  • Default:: false
  • Required: false

Users will not be able to edit hidden fields, therefore when hiding a field you should specify the default or const properties to populate these fields when new objects are created.

Example

fields:
  - type: string
    name: title
    required: true
    default: Replace with page title

Field Types

String Field

Short single-line plain text

fields:
  - type: string
    name: title
    label: Title

Data:

---
title: Lorem Ipsum
---

Slug Field

Field representing the URL slug

fields:
  - type: slug
    name: slug
    label: Slug

Data:

---
slug: blog/lorem-ipsum
---

Text Field

Multi-line plain text field

fields:
  - type: text
    name: description
    label: A short description of the article

Markdown Field

Rich text that should be run through markdownify filter.

fields:
  - type: markdown
    name: description
    label: A short description of the article

Number Field

Creates a number input field in the CMS. Can be a subtype of int (default) or float. Can be limited by min (minimum allowed value) or max (maximum allowed value). Use step to indicate jump steps.

fields:
  - type: number
    name: age
    label: The employees age
  - type: number
    subtype: float
    name: height
    label: Height

The data represented by these fields would be:

---
age: 10
height: 175.5
---

Boolean Field

A boolean true or false

fields:
  - type: boolean
    name: draft
    label: Is this article a draft?

Data:

---
draft: true
---

Image Field

The path to the image file.

If assets.refereceType is set to static, the path to the image file should be relative to the folder specified in assets.staticDir

If assets.refereceType is set to relative, the path to the image file should be relative to the content file from which the image is referenced.

Creates an image widget in the CMS which typically has extra UI options like cropping, preview etc.

fields:
  - type: image
    name: thumbnail
    label: The thumbnail image for this blog post

File Field

Path to any file, relative to the folder specified by staticDir property in stackbit.yaml . Creates a basic file upload widget in the CMS.

fields:
  - type: file
    name: whitepaper
    label: A Link to the whitepaper PDF file

Datetime Field

A date and time

fields:
  - type: datetime
    name: date
    label: Publish Date

Data:

---
title: "My Blog Post"
date: 2017-03-09T14:25:52-05:00
---

Date Field

A date

fields:
  - type: date
    name: date
    label: Publish Date

Data:

---
title: "My Blog Post"
date: 2017-03-09
---

Color Field

Color value in Hex format (e.g.: #FF0000)

stackbit.yaml

models:
  theme:
    type: data
    label: Theme Config
    file: theme.json
    fields:
      - type: color
        name: primary_color
        label: Primary Theme Color
      - type: color
        name: link_color
        label: Link Color

Data:

{
  "primary_color": "#FFCC00",
  "link_color: "#3eb2fd"
}

Enum Field

The enum field type requires specifying an options field with list of allowed values. This list can be represented in two ways:

  1. List of strings, each string is one of the allowed values.
  2. List of objects with label and value fields. The value specifies the allowed value and the label specifies the label that will be presented to the user, if the underlying CMS supports that.
fields:
  # enum with list of values
  - type: enum
    name: tag
    label: Tag
    options: [foo, bar, baz]
  # enum with list of objects
  - type: enum
    name: element
    label: Element
    options:
      - label: "Foo!"
        value: foo
      - label: My Bar
        value: bar
      - label: bazzz
        value: baz

Data:

---
tag: foo
element: bar
---

Object Field

A nested object. Some CMS's support only a flat model structure. For these CMS's, all Object fields will be transformed into Model Field.

This type of field should be used only if the nested object is not repeated in another field. Otherwise, Model Field should be used instead to minimize number of models when flattening the model tree.

Fields:

  • fields - list of model fields of the nested object
  • labelField - the name of a field that will be used as title when embedded this field inside a list or in another object.

stackbit.yaml

models:
  config:
    type: data
    label: Config
    file: config.toml
    fields:
      - type: object
        name: params
        label: Params
        description: Site parameters
        fields:
          - type: string
            name: google_analytics_id
            label: Google Analytics ID
          - type: string
            name: google_tag_manager_id
            label: Google Tag Manager ID
          - type: object
            name: logo
            label: Params Logo
            fields:
              - type: image
                name: logo
                label: Logo Image
              - type: string
                name: alt
                label: Logo Alt Text

config.toml

[params]
  google_analytics_id = ""
  google_tag_manager_id = ""
  [params.logo]
    logo = "images/logo.svg"
    alt = "My Logo"

Model Field

Fields of model type can be used to store nested objects. The advantage of model field over the object field is that model field is defined in a separate model, allowing reusing that model, while the object field is defined within the field preventing it from being reused. Additionally, the model field can store objects of several types, while the object field can only store a single type of object.

Objects referenced by the model field, must have the type field (or any other field name specified by the objectTypeKey) holding the value of the object's model name. This is required to identify the name of the model representing the object. The type field can be omitted if the model field can have an objects of a single type.

Fields:

  • models - list of models that can be set for this field. All models must be of object type - type: object

Example

For example, assume a schema with a page model that has a link field that referencing an object of the link_model model:

stackbit.yaml

# stackbit.yaml
...
models:
  page:
    type: page
    label: Page
    fields:
      - type: string
        name: layout
        const: page
        required: true
        hidden: true
      # the "link" field can only reference objects of "link_model" type
      - type: model
        name: link
        models: [link_model]
  link_model:
    type: object
    label: Link
    labelField: label
    fields:
      - type: string
        name: label
      - type: string
        name: url

page.md

---
layout: "page"
link:
  # the "type" is optional if the field can reference an object
  # of a specific model, e.g.: "link_model" only
  # type: link_model
  label: "About"
  url: "/about"
---

Hello World

Now, lets create another link_or_button field that could reference objects of link_model or button_model model types:

stackbit.yaml:

models:
  page:
    type: page
    label: Page
    fields:
      - type: string
        name: layout
        const: page
        required: true
        hidden: true
      - type: model
        name: link_or_button
        models: [link_model, button_model]
  link_model:
    ...
  button_model:
    type: object
    label: Button
    fields:
      - type: string
        name: label
      - type: string
        name: action
      - type: enum
        name: style
        options: [default, primary, secondary]

Now, because the link_or_button field can reference objects of different types, the referenced object must have the type field to allow validating and type-checking of its fields agains the schema. This type field could also be used in site template logic to execute different code paths.

index.md:

---
layout: "page"
# The "link_or_button" field must specify the "type" field to
# indicate which kind of object it references.
link_or_button:
  type: "link_model"
  label: "Try Now"
  url: "/try"
---

List Example

The model field type can also be used inside list fields.

models:
  page:
    type: page
    label: Page
    fields:
      - type: string
        name: layout
        const: page
        required: true
        hidden: true
      - type: string
        name: title
        required: true
      - type: list
        name: sections
        items:
          type: model
          models: [hero_section, features_section, faq_section]
  hero_section:
    type: object
    label: Hero Section
    fields:
      - type: markdown
        name: intro_text
        label: Intro Text
  features_section:
    type: object
    label: Features Section
    fields:
      ...
  faq_section:
    type: object
    label: FAQ Section
    fields:
      ...

index.md

---
layout: home
title: Home
sections:
  - type: hero_section
    title: ...
  - type: features_section
    features: ...
  - type: faq_section
    questions: ...
---

The type field could be also used to create conditions in templates as shown in the following example for a home.html layout file written in Nunjucks:

<h1>{{ page.title }}</h1>

{% if page.section.type == "hero_section" %}
  {{ page.section.intro_text | markdownify }}
{% elif page.section.type == "features_section %}
  ...
{% elif page.section.type == "faq_section %}
  ...
{% endif %}

Reference Field

Fields of reference type can be used to store objects by reference. The difference between the reference and the model fields is that reference field stores the object's location (for file-based CMS) or object's ID (for API-based CMS), while the model fields store the object as the field value. The reference fields are very useful when the same data needs to be referenced from multiple places.

Objects referenced by this field must have a type property identifying the name of the model representing that object.

Fields:

  • models - list of models that can be set for this field. All models must be of data type - type: data

Example

stackbit.yaml

dataDir: data
models:
  post:
    type: page
    label: Post
    folder: blog
    urlPath: blog/{slug}
    labelField: title
    fields:
      - type: string
        name: layout
        const: post
        required: true
        hidden: true
      - type: string
        name: title
        required: true
      - type: slug
        name: slug
        required: true
      - type: reference
        name: author
        models: [author]
  person:
    # type: data specifies that objects defined by this model are global,
    # and can be referenced by fields of type "reference". These objects
    # are referenced by their object ID in API-based CMS,
    # or by a file path in Git-based CMS.
    type: data
    label: Author
    folder: authors
    fields:
      - type: string
        name: first_name
        label: Author's first name
      - type: string
        name: last_name
        label: Author's last name
      - type: string
        name: bio
├── data
│   ├── config.json
│   └── authors
│       ├── bob.json
│       └── alice.json

Like with the model field, objects referenced by reference field type, must define the type field (or any other field name specified by the objectTypeKey) to indicate the object's model name.

// data/authors/bob.json
{
  "type": "author",
  "first_name": "John",
  "last_name": "Doe",
  "bio": "John Doe says Hello World"
}

In Git-based CMS, the value of the reference field will be the path to the data file:

# content/posts/hello.md
---
title: Hello
slug: hello
author: data/authors/bob.json
layout: post
---

In the example above, the author field is a referenced object represented by the person model of type data. The type of the referenced objects identified by the type field.

List Example

The reference type can be also used in lists:

stackbit.yaml

...
models:
  home:
    type: page
    label: Home
    singleInstance: true
    file: index.md
    fields:
      ...
      - type: list
        name: featured_products
        label: Featured Products
        items:
          type: reference
          models:
            - product_flower
            - product_tree
# data/products/rose.yaml
type: product_flower
name: Rose

# data/products/tulip.yaml
type: product_flower
name: Tulip

# data/products/lemon.yaml
type: product_tree
name: Lemon tree

index.md

---
layout: home
title: Home
featured_products:
  - data/products/rose.yaml
  - data/products/tulip.yaml
  - data/products/lemon.yaml
---

List Field

List field is used to represent lists of items of the same type. A list field type may have an items field where you can define the type of items in the array. By default the type is set to string.

Fields:

  • items - specifies the type and attributes of list items
  • items.type - specifies the type of the list items, default is string.
  • items.* - fields specific to the specified item type:

    • items.labelField for items.type: object
    • items.models for items.type: model and items.type: reference
    • items.options for items.type: enum

Examples:

List of strings

The example below defines a simple list of strings

fields:
  - type: string
    name: title
    label: Title
  - type: list
    name: tags
    label: Tags
    items:
      type: string

The data represented by this list in YAML (or front-matter):

---
title: JavaScript
tags:
  - code
  - javascript
  - node
---

The data represented by this list in TOML

title = "Javascript"
tags = ['code','javascript','node']

The date represented by this list in JSON

{
  title: "Javascript",
  tags: ['code','javascript','node']
}

List of enums

fields:
  - type: list
    name: categories
    label: Categories
    items:
      type: enum
      options:
        - tech
        - art
        - announcements

Data:

---
categories:
  - tech
  - art
---

List of objects

The example below defines an advanced list of nested objects

fields:
  - type: string
    name: title
    label: Title
  - type: list
    name: button
    label: Buttons
    items:
      type: object
      labelField: label  # labelField specifies which field value to use as the list item label
      fields:
        - type: string
          name: url
          label: Button URL
        - type: string
          name: label
          label: Button Label

The data represented by such list might look like this:

---
title: JavaScript
buttons:
  - label: Example Site
    url: https://www.example.com
  - label: Stackbit
    url: https://www.stackbit.com
---

List of models

Taking the previous example, the button object can be defined as a separate model and used as a list item type while preserving the structure of the represented data:

models:
  model_a:
    ...
    fields:
      - type: string
        name: title
        label: Title
      - type: list
        name: button
        label: Buttons
        items:
          type: model
          models: [button]
  button:
    type: object
    label: Button
    labelField: label
    fields:
      - type: string
        name: url
        label: Button URL
      - type: string
        name: label
        label: Button Label

This kind of architecture allow reusing the button model in other models and reduces amount of models created in an API based CMS.