Docs (Public)

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 - about.md:

---
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:

  1. A page must match a model that defines a singleInstance: true with file referencing the page itself.
  2. 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.: folder, match, exclude).

For example, the following stackbit.yaml defines five page models: home, generic_page, product, product_overview and post. Each of these models define unambiguous locations for its page files by using file, folder, match and exclude fields.

# 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: ...    

Note how generic_page excludes index.md, products/**/* and 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
...

Data Files

Themes can have CMS editable data files of the following extensions: .yml, .yaml, .json or .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 (config, social and links) and defines the corresponding data file in the file property.

#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
...

Media Files

Themes can have media files that will be editable in the CMS. These media files must be nested under a folder specified by uploadDir. The 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:

stackbit.yaml

staticDir: static
uploadDir: images

The file structure this represents has an images directory inside the static directory.

...
├── 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:

about.md

---
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:

about.md

---
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.