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

New blog page dialog

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!

Basic blog page

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.

Learn more about annotations.