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.
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
- Allowed values: Human readable label for the field. Defaults to _.startCase(fieldName).
- Required: false
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:
- List of strings, each string is one of the allowed values.
- List of objects with
label
andvalue
fields. Thevalue
specifies the allowed value and thelabel
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 objectlabelField
- 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. Allmodels
must be ofobject
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. Allmodels
must be ofdata
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 itemsitems.type
- specifies the type of the list items, default isstring
.items.*
- fields specific to the specified item type:items.labelField
foritems.type: object
items.models
foritems.type: model
anditems.type: reference
items.options
foritems.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.