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/articles/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
tourlPath
- 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