In addition to containing the required stackbit.yaml file, a theme must conform to the following requirements.
Markdown Pages with front matter
Page content must be contained in markdown files with a
.md extension and use YAML or TOML front matter:
For example -
--- title: About subtitle: About us layout: about --- # About Us This is about us section.
Unambiguous Page to Model Mapping
All pages must be unambiguously mapped to page models, meaning that every content page (
.md file) in the template must match a page model defined in the
stackbit.yaml. The only exception being excluded pages matched in the
excludePages field of stackbit.yaml.
For a page to be unambiguously mapped to a page model, one of the following requirements must be met:
- A page must match a model that defines a
filereferencing the page itself.
- A page file must match a page model using the location of the page file and corresponding model properties responsible for matching pages (e.g.:
For example, the following
stackbit.yaml defines five page models:
post. Each of these models define unambiguous locations for its page files by using
# stackbit.yaml pagesDir: content models: home: # home model can only be matched to content/index.md type: page label: Home Page Model singleInstance: true file: index.md generic_page: # generic_page model matches all md files in "content" folder, except # "index.md" and files located inside "products" and "posts" folders type: page label: Generic Page Model exclude: - index.md - products/**/* - posts/**/* product: # product model matches all md files inside content/products folder type: page label: Product Page Model folder: products exclude: _index.md fields: ... product_overview: # product_overview model can only be match to content/products/_index.md type: page label: Product Page Model singleInstance: true file: products/_index.md fields: ... post: # post model matches all md files inside content/posts folder type: page label: Post Page Model folder: posts fields: ...
posts/**/* to prevent ambiguity. The content files would map as shown below:
... ├── content │ ├── products # all pages in this folder map to "product" model except _index.md │ │ ├── _index.md │ │ ├── product1.md │ │ ├── product2.md │ │ └── product3.md │ ├── posts # all pages in this folder map to "post" model │ │ ├── post1.md │ │ ├── post2.md │ │ └── post3.md │ ├── index.md # maps to "home" model because it is singleInstance │ └── about.md # maps to "generic_page" model ...
Themes can have CMS editable data files of the following extensions:
.toml. Data files must be nested under a folder specified by
dataDir property, which can be defined as an empty string to specify the site's root folder).
The following example defines three content models (
links) and defines the corresponding data file in the
#stackbit.yaml dataDir: data models: config: type: data label: Config file: config.yaml fields: ... social: type: data label: Social Links file: footer/social.json fields: ... links: type: data label: Footer Links file: footer/links.yaml fields: ...
... ├── data │ ├── footer │ │ ├── social.json │ │ └── links.yaml │ └── config.yaml ...
Themes can have media files that will be editable in the CMS. These media files must be nested under a folder specified by
uploadDir itself must be relative and inside the
staticDir. The reason for that is that Git-based CMS such as Forestry and NetlifyCMS can only store and read media files from a specific folder that is be publicly available after SSG builds and deploys. For API-based CMS, Stackbit reads all files from
uploadDir and uploads them to the CMS. Then it replaces all references to these files in data and page files with absolute URLs received from CMS.
Let's look at an example to better illustrate this:
staticDir: static uploadDir: images
The file structure this represents has an
images directory inside the
... ├── static │ ├── images │ │ ├── logo.png │ │ ├── ... │ │ └── demo.jpg │ ├── js │ │ └── ... │ ├── css │ │ └── ... │ └── ... ...
Now let's look at how this would impact our content, given a simple markdown file with a media file defined in the front matter and another in the body:
--- title: About logo_image: images/logo.png --- About page ![Demo Image](images/demo.jpg)
When this page is uploaded to an API-based CMS, the images will be uploaded first. Then all image references within the content are replaced with their absolute URLs from the CMS as below:
--- title: About logo_image: https://www.example-cms.com/some-project-assets/logo.png --- About page ![Demo Image](https://www.example-cms.com/some-project-assets/demo.jpg)
Finally, page and data files are uploaded to the CMS.