Page Models describe the structure of site pages stored in markdown files. They extend the common properties defined in the base Model.

To better understand how a page model describes a page, let's look at the following example that models an "article" page in the "articles" folder. In this case our page files are located in pagesDir: content. The "articles" folder contains all the articles in our site. The following markdown page is one of these articles stored in content/aritcles/installing-node.md file:

---
title: How to install Node.js
image_thumbnail: images/screenshot.jpg
show_image: true
---

# Et perhorruit quoque revocataque vellem

## Angue poma dentibus

Aridus nostra abstractus viris
vitataque labores hiatus ultima, favistis Hippothousque vincemus cum, nymphae
[triformis aera quae](http://aether-diurnos.io/tamen.aspx) templa.

The following page model defined in the stackbit.yaml describes the structure of all markdown files in the "articles" folder, including the article page shown above. Note that the root folder for all page files is defined inside the pagesDir field, and all page model properties, such as folder, are relative to pagesDir.

pagesDir: content # the root folder of all markdown pages
models:
  article: # the name of the article model is "article"
    type: page # page models should always have the "page" type
    label: Article # the label of the model, shown in CMS UI
    folder: articles # the folder, relative to pagesDir, where markdown files of this model are located
    match: 
      - "**/*" # match all files and subfolders in the "articles" folder
    exclude:
      - "index.md" # exclude the "index.md" file in the articles folder
    urlPath: "/articles/{slug}" # the url pattern of the article pages
    fields: # model fields
      - type: string
        name: title
        label: Title
        description: The title of the article
        required: true
      - type: string
        name: image_thumbnail
        label: Image
        description: The article image
      - type: boolean
        name: show_image
        label: Show Image
        description: Show or hide the image

Page Model Properties

hideContent

  • Allowed values: boolean
  • Default value: false
  • Required: false

Set to true for page models that do not have markdown content below the front-matter

urlPath

  • Allowed values: a fixed or dynamic URL path
  • Default value: /{slug}
  • Required: false
  • Example value: /blog/{slug}

Stackbit Studio uses urlPath property to help users create pages and navigate their site.

This can either be a fixed path for page models that are marked as singleInstance or a dynamic pattern for models that can have multiple pages. To create dynamic pattern use curly braces with tokens: {title}.

When using API-based CMS, the tokens should be named after fields available in the model. For example, a blog post model likely has a slug field representing the path to the specific post within the blog, so a post page model should contain a slug token inside urlPath - /blog/{slug}.

When using git-based CMS, the slug will be extrapolated from the filePath. For example, if the filePath is /blog/{slug}.md and the file representing the blog post is stored at /blog/hello.md, the extrapolated slug will be hello and the interpolated urlPath will be /blog/hello.

filePath

  • Allowed values: a file path pattern relative to pagesDir
  • Default value: computed by appending .md to urlPath
  • Required: false
  • Example value: posts/{slug}.md

Stackbit Studio use the filePath property to create new page files. You need to specify this property only when your project uses git-based CMS.

This can either be a fixed path for models that are marked as singleInstance or a dynamic pattern for models that can have multiple pages. To create dynamic pattern use curly braces with tokens: {title}.

For example, if your blog posts files are stored in the blog folder, you can use the blog/{slug}.md pattern. When creating a new blog post in Stackbit Studio, the {slug} token will be replaced with a string provided by the user, and the new page will be saved at {pagesDir}/blog/{slug}.md.

When the file paths of your page model correspond to their url paths, you don't need to specify filePath. For example, if your pagesDir is content and your page files correspond to their url path, there is no need to specify filePath (note index.md is always collapsed):

  • content/index.md => /
  • content/about => /about
  • content/articles/index.md => /articles
  • content/articles/hello.md => /articles/foo
  • content/articles/world/index.md => /articles/world

On the other hand, if page model files do not correspond to their url paths, you need to specify the correct filePath:

  • _posts/hello.md => /blog/hello
  • _posts/world.md => /blog/world

In this case, the urlPath would be /blog/{slug} and the filePath would be _posts/{slug}.md

Example:

ssgName: jekyll
pagesDir: content
models:
  
  home:
    type: page
    label: Home Page
    # singleInstance: true ensures that only one instance of this page exists
    singleInstance: true
    # the urlPath and filePath can be static
    urlPath: "/"
    filePath: "index.md"

  page:
    type: page
    label: Basic Page
    # the urlPath and filePath can be dynamic patterns with tokens
    # here both urlPath and filePath can be omitted as urlPath is set to default
    # value and filePath correspond to the urlPath
    urlPath: "/{slug}"
    filePath: "{slug}.md"
    fields:
      ...

  post:
    type: page
    label: Blog Post
    # the urlPath and filePath doesn't have to be the same. For example in Jekyll,
    # the posts are stored in _posts folder but can be configured to be published
    # under /blog url path
    urlPath: "/blog/{slug}"
    filePath: "_posts/{slug}.md"
    fields:
      ...

Page Model Matching Properties

Each markdown file in your themes pagesDir must match a single page model. If a file matches multiple page models you will get a validation error.

The front-matter within a matched page must line up with the model fields nested inside the page model that it matched. You may use the global excludePages to exclude markdown files from matching.

For more details about pagesDir and excludePages, check the stackbit.yaml documentation page.

You can control how files are matched to page models using the configuration options below. If no matching options are provided, a page model uses the following defaults:

folder: ""
match: "**/*"
exclude: []

file

Matches a single markdown file relative to the pagesDir folder.

Cannot be combined with folder, match and exclude matching options.

Required if singleInstance: true

stackbit.yaml

pagesDir: content
models:
  home:
    type: page
    label: Home
    file: "homepage.md"
├── stackbit.yaml
├── content
│   ├── posts
│   │   ├── index.md
│   │   ├── post1.md
│   │   ├── post2.md
│   │   └── post3.md
│   ├── homepage.md       # will match this file
│   └── about.md
│   └── product.md

singleInstance

Should be set too true for files that should have only one page instance (e.g.: home). If a file is marked as singleInstance in one model then you don't need to exclude it in all the other models.

For example, given the following configuration with two page models:

stackbit.yaml

pagesDir: content
models:
  home:
    type: page
    label: Home
    file: "posts/index.md"
    singleInstance: true
  blog:
    type: page
    label: Blog Posts
    folder: posts

The home model marked as singleInstance will match index.md while the blog model will match all other files in the posts folder. There won't be a validation error because index.md does not need to be excluded from the blog model as it was matched by a singleInstance model.

├── stackbit.yaml
├── content
│   ├── posts
│   │   ├── index.md    # "home" will match this file but "blog" will skip it because "home" uses singleInstance   
│   │   ├── post1.md    # "blog" will match this file
│   │   ├── post2.md    # "blog" will match this file
│   │   └── post3.md    # "blog" will match this file
│   ├── homepage.md       
│   └── about.md
│   └── product.md

folder

Matches all markdown files inside a folder relative to the pagesDir folder.

The default value for folder is an empty string. If folder is not set for a page model the default value will be used, which means it will match all .md files under pagesDir.

This value can be combined with the match and exclude matching options to fine tune the files that are match. These options are relative to the folder when it is defined. For example, if the folder value was posts and the match value was ["index.md", "about.md"], the content model would match posts/index.md and posts/about.md.

This field is mutually exclusive with singleInstance: true.

stackbit.yaml

pagesDir: content
models:
  blog:
    type: page
    label: Blog Posts
    folder: posts
├── stackbit.yaml
├── content
│   ├── posts           # will match all files inside this folder
│   │   ├── index.md
│   │   ├── post1.md
│   │   ├── post2.md
│   │   └── post3.md
│   ├── homepage.md       
│   └── about.md
│   └── product.md

The following is an example of combining exclude with folder:

stackbit.yaml

...
pagesDir: content
models:
  blog:
    type: page
    label: Blog Posts
    folder: posts
    exclude: 
      - "index.md" 

All files other than the excluded file will be matched. However, index.md would still need to match a separate page model.

├── stackbit.yaml
├── content
│   ├── posts
│   │   ├── index.md    # will exlcude this file
│   │   ├── post1.md    # will match this file
│   │   ├── post2.md    # will match this file
│   │   └── post3.md    # will match this file
│   ├── homepage.md       
│   └── about.md
│   └── product.md

match

A glob pattern used to match markdown files. match supports both glob and list values. The following examples all achieve the same match:

match: ["index.md", "about.md"]
match: "{index.md,about.md}"
match:
  - "index.md"
  - "about.md"

The default value is **/*, which will match all the files in all subfolders as specified by the folder vale for the page model. match is relative to folder. If folder is not set for a page model the default value of "" is used, which is the equivalent of pagesDir.

Internally the "micromatch" NPM module is used to match the files.

This field is mutually exclusive with singleInstance: true

stackbit.yaml

pagesDir: content
models:
  basicpage:
    type: page
    label: Basic Page
    match: 
      - "*.md"
├── stackbit.yaml
├── content
│   ├── posts
│   │   ├── index.md
│   │   ├── post1.md
│   │   ├── post2.md
│   │   └── post3.md
│   ├── index.md       # will match this file
│   └── about.md       # will match this file
│   └── product.md     # will match this file

exclude

A glob pattern used to exclude markdown files inside the specified folder. The paths listed must be relative to folder.

By default it does not exclude any files.

Internally the "micromatch" NPM module is used to match the files.

This field is mutually exclusive with singleInstance: true

stackbit.yaml

pagesDir: content
models:
  basicpage:
    type: page
    label: Basic Page
    match: "*.md"
    exclude: 
      - "_index.md"
├── stackbit.yaml
├── content
│   ├── posts
│   │   ├── post1.md
│   │   ├── post2.md
│   │   └── post3.md
│   ├── _index.md      # will exclude this file
│   └── about.md       # will match this file
│   └── product.md     # will match this file

Ready to get started?