When building a blog, you can either begin with individual posts or the main blog page. Here we're going to build out the blog page first. Because we don't yet have posts, we'll focus on the basics of adding a new page type.
In the next lesson, we'll add individual posts and add a feed of posts to the blog page.
Concepts covered in this lesson:
- Content modeling basics
- Stackbit configuration
- Content storage and editing
- Next.js pages
- Processing and delivering content via Sourcebit
- Unlocking visual editing through annotations
Add Blog Page Model
Every editable content object must be modeled so that Stackbit knows how to render the editor controls. Models are placed in the .stackbit/models
folder. If you look, there are already a few models that come with the starter.
To keep things simple, let's add a BlogPage
model to represent our new page type. For now, we'll give it a single title
field.
# .stackbit/models/BlogPage.yaml
name: BlogPage
layout: Blog
label: Blog
hideContent: true
fields:
- type: string
name: title
required: true
Learn more about content modeling options and field definitions.
Configure Blog Page
There are three types of models with Stackbit: page
, data
, and object
. With page models, there are a few additional properties to define. This is done in the main configuration file — stackbit.yaml
in the root of your project.
Add a BlogPage
property to the contentModels
config with the following content:
# stackbit.yaml
# ...
contentModels:
Page:
# ...
BlogPage:
isPage: true
singleInstance: true
urlPath: '/blog'
file: 'blog/index.md'
newFilePath: 'blog/index.md'
This configuration is noting:
BlogPage
is a page model (isPage: true
).- There should only be a single page for this model (
singleInstance: true
). - The URL for the page is
/blog
. - If the content source for the page should be
content/pages/blog/index.md
. (Note:content/pages
comes from thepagesDir
option, also set in this file.)
Learn more about defining content models.
Add Blog Page Content
Now you have everything you need to be able to create the blog page.
Make sure your Next.js development server is running and that you are running Stackbit dev. (If not, see the intro.)
Click the plus icon to create a new Blog page.
Note that the value you put for the slug does not matter in this instance because we've hard-coded the URL for the page to be /blog
.
Because we created this page content before the Next.js page code, we are led to a 404 error. Let's fix that.
Add Blog Page Component
Let's add a simple page to pages/blog/index.jsx
. All we want it to do is render the title for now.
// pages/blog/index.jsx
import { pagesByLayout } from '../../utils/sourcebit-utils'
const BlogPage = ({ page }) => {
return (
<div>
<h1>{page.frontmatter.title}</h1>
</div>
)
}
export default BlogPage
export const getStaticProps = async () => {
const page = pagesByLayout('Blog')[0]
return { props: { page } }
}
Your browser should live reload to show the blog page! (If it doesn't, refresh the browser.) And there it is!

Learn more about Next.js pages.
Understanding Sourcebit
Next.js makes no inference as to how you're going to work with content. It simply provides the mechanism to render what you provide.
Our preference is to load content with an open-source library we built called Sourcebit. Sourcebit is configured in sourcebit.js
, which defines where the content source. After finding content, Sourcebit caches it in .sourcebit-nextjs-cache.json
at the root of the project.
Sourcebit continues watching for content changes while the Next.js development server is running.
Our minimal starter has a series of utility methods that help pages work with this content. One example of this was what you dropped into the getStaticProps()
method above, calling pagesByLayout()
. Take a look through the utils
directory to get a better sense of how content is being processed and delivered to pages.
Make Page Title Editable
The magic of Stackbit is in being able to click on content on a page and editing it in place. This feature is enabled through a process called annotation.
With annotations, we use a combination of data attributes to tell Stackbit exactly how to map content from markdown files to HTML elements on the page.
To annotate the title of the blog page, add data-sb-object-id
on a wrapping element, and data-sb-field-path
to target the specific element we want to be editable. It looks like this:
// pages/blog/index.jsx
const BlogPage = ({ page }) => {
return (
<div data-sb-object-id={page?.__metadata?.id}>
<h1 data-sb-field-path="title">{page.frontmatter.title}</h1>
</div>
)
}
Visual Editing Unlocked!
Now you can hover over the title, click it, and edit the content! Do it, then look back in your content/pages/blog/index.md
file to see that the contents changed.
Understanding Validations
When using local content, the value of data-sb-object-id
should be the path to the content file from the root of the project. This is automatically generated for us by Sourcebit, which is why we can use page.__metadata.id
for this value. In this case, the value resolves to content/pages/blog/index.md
. (You can inspect your browser to make sure.)
data-sb-field-path
then enables us to drill down into the data structure of that page and target a single property, which is title
in this case.
Getting Started Lessons