How to Create a Blog with Stackbit and Next.js
Tags: javascript, webdev, programming, tutorial
Published: 2022-04-20 09:46:21

---
title: How to Create a Blog with Stackbit and Next.js
published: true
date: 2022-04-20 08:10:59 UTC
tags: Javascript,webdev,programming,tutorial
canonical_url: https://blog.shahednasser.com/how-to-create-a-blog-with-stackbit-and-next-js/
cover_image: https://blog.shahednasser.com/static/da978a60198d62ff80ba9549febf0484/How-to-Create-a-Blog-with-Stackbit-and-Next.js-2.jpg
---

_Originally Published on [my personal blog](https://blog.shahednasser.com/how-to-create-a-blog-with-stackbit-and-next-js/)._

[Stackbit](https://www.stackbit.com) is a website builder that gives both technical and non-technical people a lot of power when creating their websites. It can be used to create portfolio websites, blogs, or any type of website if you wish to extend it to your use case.

In this tutorial, you'll learn how to create a blog with Stackbit using its Next.js starter theme. You'll also learn how to add custom pages for Content Models by creating an Authors page.

## Project Setup

Start by [choosing one of the Starter theme](https://app.stackbit.com/create/theme). This tutorial will be focused on the [Starter th](https://starter-nextjs.stackbit.app)eme.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-16-at-7.03.36-PM.png)

Then, choose a name for your new project.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-16-at-7.03.57-PM.png)

If you're not signed in you'll then be asked to either create an account or sign in. I recommend creating an account with GitHub as it will be easier to connect your repository to it then.

You'll then have your website ready for customization.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-09-at-6.00.40-PM.png)

Notice that your website will be deployed on a free Stackbit subdomain. So, you'll be able to view it online right away.

## Transfer Repository to Your Account

The next step is to transfer the website codebase to your GitHub account. This makes it possible for you to make changes to the website's codebase and add new content models.

Click on the gear icon at the top left. Then, under "Connected Services" you'll see GitHub and you'll be able to Request Repo Transfer.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-09-at-6.01.32-PM.png)

When you click on that you'll receive an email to accept the transfer. Once you click on the link in the email, the transfer will begin and might take a couple of minutes.

Once the transfer is done, you'll have your website's codebase in you GitHub account.

## Understanding the Branches

In your GitHub repository, you'll have 2 branches: the `master` branch and the `preview` branch.

The `master` branch is the deployed version that everyone can see when they go on your website.

The `preview` branch is what you can see when you log in on Stackbit. Think of it as a draft version. Once you think the changes are ready to be deployed on the main website, you can either push the changes to the master branch manually or just click the "Publish" button at the top right in your Stackbit app.

## Set Up Local Development

Stackbit has a code editor that you can use right in your Stackbit app by clicking on the code icon in the sidebar.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-17-at-1.24.09-PM.png)

Once you make a change in the code, it will be automatically committed to the `preview` branch which is what you see in your Stackbit app.

Alternatively, you  can work on your website's development locally. To do that, click on the gear icon at the top left again. Under "Envoironment" you'll see "Local Development" with steps you can copy and paste into your terminal directly.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-09-at-6.05.11-PM.png)

Please note that if you haven't transferred the codebase into your GitHub account you won't be able to see these tips.

As mentioned under "Local Development", once you push commits to the `preview` branch, the visual editor in your Stackbit app will update automatically.

## Creating Posts

There are 2 ways to create posts: through the visual editor or through the code editor.

### Visual Editor

On your Stackbit app, if you press the second icon "CMS" you'll be able to edit and add pages and blog posts on your website.

Try clicking on "Post" then "Add new Post". You'll be able to enter information like slug and title. Then, you can select a feature image and the author.

You can then use the content editor, which has text formatting you can use but also supports raw markdown editing by pressing the Raw MD button.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-09-at-6.40.49-PM.png)

All changes you make to posts are automatically committed to the `preview` branch. Once you publish them they'll be live on your deployed website.

### Code Editor

To add posts in the code editor, go to `content` then `pages`. You'll see all pages there in markdown files, where the names of the files are the slugs of the pages.

You'll also find a `blog` directory which holds all posts inside it. To add a blog post create a new file with its name the slug you want for the post. Then, add in it the following information:

```
---
title: Test Post
layout: PostLayout
date: '2021-07-01'
author: content/data/team/hugh-saturation.json
excerpt: >-
  Sed in facilisis dui. Nulla molestie risus in mi dapibus, eget porta lorem
  semper. Donec sed facilisis nibh.
featuredImage:
  type: ImageBlock
  url: /images/post-2.jpg
  altText: Post Image
bottomSections:
  - elementId: ''
    variant: variant-c
    colors: colors-a
    title: Read next
    recentCount: 3
    styles:
      self:
        height: auto
        width: wide
        margin: ['mt-0', 'mb-0', 'ml-0', 'mr-0']
        padding: ['pt-12', 'pb-56', 'pr-4', 'pl-4']
        justifyContent: center
      title:
        textAlign: center
      subtitle:
        textAlign: center
      actions:
        justifyContent: center
    type: RecentPostsSection
---

This is test post

```

Everything between the opening and closing 3 dashes are the values of the fields you enter in your visual editor. That includes the title, author, feature image, and more.

Then, after the three dashes is the markdown content of the post. This is the content you'd enter in the text editor in the visual Stackbit app, but it should be in markdown format.

Once you're done, save the new file and commit it to the `preview` branch. You'll be able to see it in the visual editor among the CMS.

If you also open the Blog page in your Stackbit app or open the website locally, you should see the post you added among other existing posts.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-09-at-6.18.11-PM.png)

## Add Pages for Authors

In this section, you'll start to customize your Stackbit starter. You'll be adding a new predefined type of page to display authors. You'll need to create a layout specific for that page before creating that page.

### Add Page to Content Models

Open `stackbit.yaml` in the root of your website's code and add the following under `contentModels`:

```
contentModels:
	...
    PersonFeedLayout:
    	isPage: true
    	singleInstance: true
    	urlPath: '/authors'
    	file: 'authors.md'
    	newFilePath: 'authors.md'
```

You're adding a new layout `PersonFeedLayout`. You can read more about [content model fields in Stackbit's documentation](https://docs.stackbit.com/reference/stackbit-yaml/mapping-content-models/), but briefly:

1. If `isPage` is set to `true` the UI will allow you to create pages using this model.
2. `singleInstance` means that this page can only be created once.
3. `urlPath` is the path that this page will be found on.
4. `file` is the markdown file that holds the data and content for this page. Since this is a page, its path is relative to `content/pages`
5. `newFilePath` is the file that should be created when this page is created through the UI. Similarly, since this content model is a page the path is relative to `content/pages`.

### Define the Content Model Fields

In this section, you'll define the fields of the new content model `PersonFeedLayout`. This means that when you try to create the page through the UI, these fields is what you will see.

To do that, create the file `.stackbit/models/PersonFeedLayout.yaml` with the following content:

```
name: PersonFeedLayout
label: Authors
labelField: title
layout: PersonFeedLayout
hideContent: true
extends:
  - Seo
fields:
  - type: string
    name: title
    label: Title
    default: This is a page title
  - type: list
    name: topSections
    label: Top Sections
    items:
      type: model
      groups:
        - sectionComponent
  - type: list
    name: bottomSections
    label: Bottom Sections
    items:
      type: model
      groups:
        - sectionComponent
  - type: style
    name: styles
    styles:
      title:
        fontWeight: ['400', '700']
        fontStyle: ['normal', 'italic']
        textAlign: ['left', 'center', 'right']
    default:
      title:
        textAlign: center
```

You can learn more about [Models in Stackbit through their documentation](https://docs.stackbit.com/reference/defining-models/), but briefly the items under `fields` are what you'll see in the UI and the fields you can enter for this content model. This content model has 4 fields:

1. `title`: the title of the page
2. `topSections`: Sections you want to add to the top of the page. This is useful if you want to allow users using the visual editor to add custom sections before your defined layout.
3. `bottomSections`: Similarly to `topSections`, you'll allow users using the visual editor to add custom sections after the defined layout.
4. `styles`: Allow the users using the visual editor to customize some of the style of the layout. 

### Create New Layout

Next, you'll be creating the `PersonFeedLayout` which will hold the implementation of the Authors page.

Create a new file `src/components/layouts/PersonFeedLayout/index.tsx` with the following content:

```
import * as React from 'react';

import ImageBlock from '../../molecules/ImageBlock';
import { getBaseLayoutComponent } from '../../../utils/base-layout';
import { getComponent } from '../../components-registry';

export default function PageLayout(props) {
    const { page, site } = props;
    const BaseLayout = getBaseLayoutComponent(page.baseLayout, site.baseLayout);
    const topSections = page.topSections || [];
    const authors = page.authors || [];
    const bottomSections = page.bottomSections || [];

    return (
        <BaseLayout page={page} site={site}>
            <main id="main" className="sb-layout sb-page-layout">
                {page.title && (
                    <h1 className="text-center my-5" data-sb-field-path="title">
                        {page.title}
                    </h1>
                )}
                {topSections.length > 0 && (
                    <div data-sb-field-path="sections">
                        {topSections.map((section, index) => {
                            const Component = getComponent(section.type);
                            if (!Component) {
                                throw new Error(`no component matching the page section's type: ${section.type}`);
                            }
                            return <Component key={index} {...section} data-sb-field-path={`sections.${index}`} />;
                        })}
                    </div>
                )}
                <div className='grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-10 my-16 max-w-screen-md mx-auto'>
                    {authors.map((author, index) => (
                        <div className='group text-center' key={index}>
                            {author.image && <ImageBlock {...author.image} 
                                className="group-hover:shadow-md transition-shadow rounded-full w-40 h-40 mx-auto" />}
                            <h3>{author.firstName} {author.lastName}</h3>
                            <span className="text-gray-500">{author.role}</span>
                        </div>
                    ))}
                </div>
                {bottomSections.length > 0 && (
                    <div data-sb-field-path="sections">
                        {bottomSections.map((section, index) => {
                            const Component = getComponent(section.type);
                            if (!Component) {
                                throw new Error(`no component matching the page section's type: ${section.type}`);
                            }
                            return <Component key={index} {...section} data-sb-field-path={`sections.${index}`} />;
                        })}
                    </div>
                )}
            </main>
        </BaseLayout>
    );
}
```

First, notice that you display the `topSections` first and the `bottomSections` last in your layout.

In the middle, you display the authors in a grid. The authors are received in the props of the layout. You'll be defining this in the next section.

After creating this layout, add it in `src/components/layouts/index.tsx`:

```
import PostFeedLayout from './PostFeedLayout';
//...

export {
	...,
    PersonFeedLayout
}
```

Finally, you need to add it to `src/components/components-registry.ts`:

```
const components = {
    //...,
    'PersonFeedLayout': dynamic(() => import('./layouts/PersonFeedLayout'))
};
```

### Add Props

To define the props passed to this layout, first, go to `src/utils/data-utils.js` and add a new function:

```
export function getAuthors(objects) {
    return objects.filter((object) => object.type === 'Person');
}
```

The `sourcebit-target-next` plugin will use the `sourcebit-source-filesystem` to read files under `content` and import them into your Stackbit website.

There are two types of content: pages under the `content/pages` directory and data under `content/data` directory. You'll be able to filter out content based on the `type` field for data content, or the `layout` field for pages content.

In this case, you're retrieving all authors, which are data content. So, you check if the `type` field is `Person`. Please note that, by default, all authors are under `content/data/team` in JSON files.

Next, you'll use this function to pass the authors as a prop to the layout you created in the previous section. Go to `src/utils/static-props-resolvers.js` and add the following:

```
import {
    //...,
    getAuthors
} from './data-utils';

//...

const StaticPropsResolvers = {
    //..,
    PersonFeedLayout: (props, data) => {
        return {
            ...props,
            authors: getAuthors(data.objects)
        };
    }
};
```

Your Next.js website will resolve the props of the layouts by checking through the `StaticPropsResolvers` object. The key is the name of the layout and the value is a function that returns an object which will be the props of the layout.

You add a new key for `PersonFeedLayout` which accepts `props` and `data` as parameters. `props` is the data entered by the user in the UI for the fields you created for the content model earlier. For example, the `bottomSections` field.

The `data` is all the data on your website made available by `sourcebit-target-next` as explained earlier. It is an object that has 3 properties:

1. `objects` which is an array of all content files loaded by the `sourcebit-source-filesystem` plugin.
2. `pages` which is an array holding all static page props.
3. `props` which is an object with common props for all pages.

In this function, you return all the props as-is and you add the `authors` prop which will call the `getAuthors` function you created earlier passing it `data.objects`.

### Add the Authors Page

Finally, you just need to add the Authors page. Create the file `content/pages/authors.md` with the following content:

```
---
title: Authors
layout: PersonFeedLayout
topSections:
  - type: CtaSection
    elementId: ''
    colors: colors-a
    backgroundSize: full
    title: Let's do this
    text: >-
      The Stackbit theme is flexible and scalable to every need. It can manage
      any layout and any screen.
    actions:
      - type: Button
        label: Try it now
        url: /
        style: primary
    backgroundImage: null
    styles:
      self:
        height: auto
        width: narrow
        margin:
          - mt-0
          - mb-0
          - ml-0
          - mr-0
        padding:
          - pt-24
          - pb-24
          - pl-4
          - pr-4
        alignItems: center
        justifyContent: center
        flexDirection: col
      title:
        textAlign: left
      text:
        textAlign: left
      actions:
        justifyContent: flex-start
---

```

This defines the page to use the `PersonFeedLayout` and adds among its top sections a Call to Action (CTA) section.

If you run your server now:

```
npm run dev
```

and go to `/authors`, you'll be able to see all the authors in your blog.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-17-at-2.24.40-PM.png)

If you push the changes to the `preview` branch you'll be able to see your new page in the Stackbit app as well as edit the page fields.

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-17-at-2.25.29-PM.png)

### Add Link to Page in the Header

Optionally, you can add a link to the page in the header. To do that, open `content/data/config.json` and add the new link under `primaryLinks` in `header`:

```
{
	...,
    "header": {
    	...,
        "primaryLinks": [
        	...,
            {
                "type": "Link",
                "label": "Authors",
                "altText": "Authors",
                "url": "/authors"
            }
        ]
    }
}
```

If you save the changes and view the website in local development, or push the changes to the `preview` branch to view it on the Stackbit app, you'll see a new link the navigation bar for "Authors".

![How to Create a Blog with Stackbit and Next.js](https://backend.shahednasser.com/content/images/2022/04/Screen-Shot-2022-04-09-at-6.44.22-PM.png)

## Conclusion

In this tutorial, you learned how you can set up Stackbit and do some development and customization on it. For more features, be sure to check out [Stackbit's documentation](https://docs.stackbit.com) for more details.