The contentModels object defines a few model-related settings that our UI needs, but are not set within model definitions (due to separation of concerns).

This includes:

  1. Which model types are listed when the "Add New Page" button is clicked in the UI, where in the filesystem to store these new pages (when using the default Git CMS), and the mapping between files and URLs.
  2. Which non-page models (e.g. Person) can be added via the UI, and where to store added content.

Generally, only model types which the UI should allow adding need to be listed.

Example

stackbitVersion: ~0.4.0
# ...
dataDir: content/data
pagesDir: content/pages
# ...
contentModels:
  PageLayout:
    isPage: true
    urlPath: '/{slug}'
    newFilePath: '{slug}.md'
  PostLayout:
    isPage: true
    urlPath: '/blog/{slug}'
    newFilePath: 'posts/{slug}.md'
  Person:
    newFilePath: 'team/{slug}.json'

Properties

isPage

For each of the model names in this list, this property controls whether the UI will allow instantiating that model as a page. The default is false.

When this is true, you may need to also define urlPath.

newFilePath

Note: this only applies to Git CMS.

The UI will store newly added pages at {pagesDir}/{newFilePath} and non-pages under {dataDir}/{newFilePath}.

In the above example, newFilePath uses the built-in variable{slug} . This is the path that the user enters in the UI when adding content, e.g. "about", "features/enterprise", and so on, potentially including multiple sub-directory names.

The new content will be formatted according to the file extension you set in this property. It can be either json, md, yaml and toml.

Given the above example snippet:

  • A new page of type PageLayout which the user names "about" will be stored in content/pages/about.md.
  • New page of type PostLayout will be stored under content/pages/posts/.
  • New instances of Person (created in the CMS view) will be stored under content/data/team/ in JSON format.

urlPath

Default URL mapping

By default, the UI will that any page content maps to URLs using their slug. This has the same meaning as explicitly setting: urlPath: '/{slug}'.

With the built-in Git based CMS, the slug is simply the path to the file relative to pagesDir, excluding the file extension.

Continuing with the examples above, the file content/pages/about.md whose type is PageLayout will be mapped to the URL /about , and vice versa.

When should I explicitly set the URL path?

As long as the file structure under pagesDir matches the URL structure of your website, there's no need. However, if the structure differs for some models, you will typically need to set both urlPath and newFilePath.

For example, here's how to define that blog posts should be saved under posts/<post-name>.md, but their URL should be /blog/<post-name>:

contentModels:
  # ...
  PostLayout:
    isPage: true
    urlPath: '/blog/{slug}'
    newFilePath: 'posts/{slug}.md'

Automatic handling of index pages

The UI has special handling for index pages:

  • When a user adds a new page and sets its path it /plans/ (note the trailing slash!), the page content will be stored to the file /content/pages/plans/index.md
  • When you navigate to this page, the UI will know to map the URL /plans/ back to /content/pages/plans/index.md.

Configuring URL paths for an API-based CMS

The slug concept is common in many CMS systems and site generators. It's a special field which is used to map the content item to a URL. The slug may be automatically generated from another field (e.g. the title) or it could be manually set. Typically, the field holding the slug is simply called slug as well.

By default, urlPath is set to '/{slug}'. This means URLs are mapped directly to the slug field in the content piece, but you can specify another field name instead.

One common need is to tweak the urlPath depending on the model type, e.g. for all content items of type Post in the CMS, setting urlPath: '/blog/{slug}'.