To follow this tutorial you only need a free Stackbit account, since it's all performed on your local machine. However, sharing your work with others via a Stackbit project requires a paid plan.

This guide covers the process of adding Stackbit to an existing Next.js site that uses Contentful as its data source.

What We're Building

To make this feel like a real-world project, we're going to use a forked version of the official Next.js + Contentful example. The changes made to the example were to provide conveniences in setting up the project and minimizing the amount of non-Stackbit work you'd have to do to complete this tutorial. Here's a summary of the changes.

To avoid conflicts with any existing content you may have, you'll be creating a new (free) Contentful space that provides content to the project.

When we're done, we'll have a Next.js site with bi-directional editing capabilities with Contentful. We'll have unlocked visual editing for one small portion of the site (the blog post title). But you'll have the foundation of knowledge and confidence to be able to apply this to any existing project at any scale.

Working with Your Site

You're likely going through this process because you have an existing site. You're welcome to skim and apply what you feel is necessary.

Tutorial Prerequisites

Before starting this tutorial, ensure you have the following:

  • A Contentful account (you'll create the space as part of the process)
  • Node v14 or greater

Understanding the Process

After we get through setting up the project on your machine, this tutorial is a four-step process. To learn more about each step in the process, visit the generic integration guide.

And with that, let's get into it!

Getting Help

If you get stuck along the way, drop into our Discord server and send a message in the #documentation channel.

1. Setting Up the Project

We're going to start from our fork of the Next.js example and get it running locally before beginning to integrate Stackbit.

Clone the Forked Example

Let's begin by using the handy create-stackbit-app to create a new site on your local machine. After navigating to your working directory, run the following command:

npx create-stackbit-app@latest --example tutorial-contentful
cd tutorial-contentful

This placed the project in a tutorial-contentful directory. You should now be in that directory with a fresh project.

Set Up Contentful

Follow the steps in the README to create a blank Contentful space. Then import the content, which will give you a single post with an image and author.

Run Development Server

In your terminal run the Next.js development server and navigate to http://localhost:3000/ to make sure everything looks right.

Next.js + Contentful site up and running

Now we're ready to move on to integrating Stackbit.

Use Preview Content

The first step is to pull in preview content. Although this is a single line of code, we left this for you to change because it is a critical part of the process that you want to ensure is properly configured.

The forked example has been adjusted such that setting PREVIEW_MODE in lib/constants.js changes the behavior of the application.

export const PREVIEW_MODE = true

After you make this change, try changing content in Contentful (without publishing), then refreshing the page to ensure draft content is being pulled in.

Work in draft mode

2. Set Up Stackbit Local Development

Now we have everything in place to begin to bring Stackbit into the site.

Configure Stackbit

When using a headless CMS, the only configuration you're required to have is a stackbit.yaml file in the root of your project. For this simple case, add the following config:

# stackbit.yaml

stackbitVersion: ~0.5.0
ssgName: nextjs
cmsName: contentful
nodeVersion: '14'
buildCommand: npm run build
publishDir: .next
modelsSource:
  type: contentful
models:
  post:
    type: page
    urlPath: '/posts/{slug}'

Much of this is standard for Next.js projects. The piece to make careful note of is the models property, which states that we have a single model called post of type page, where the posts live at /posts/[slug] URL.

Typically you'd have another model for individual pages, such as the home page, but we're keeping this simple and focusing exclusively on being able to edit the post title on the post detail page.

Learn more about Stackbit configuration.

Install Stackbit CLI

Next, install Stackbit CLI. It's recommended to do this globally, as shown below.

npm install -g @stackbit/cli@latest

Run Stackbit Dev

Once you have the CLI installed, you have the stackbit command available on your machine. In a new terminal window/tab, you can now boot Stackbit's local development environment, replacing the appropriate values below with your keys.

stackbit dev -d . -c contentful --contentful-space-id [SPACE_ID] --contentful-preview-token [PREVIEW_TOKEN] --contentful-management-token [MANAGEMENT_TOKEN]

⚠️ Be cautious when pasting sensitive values in a terminal.

Test It!

Running this command will provide a bit of output. Look toward the end for a Stackbit URL, looking something like this:

info: ⚡ Open https://app.stackbit.com/local/... in your browser

Open that URL in your browser and you should now see Stackbit's development environment. Notice that you can move around and even navigate to the post detail page, but you can't highlight or edit anything directly.

Stackbit local dev with Contentful example

3. Enable Visual Editing

Now let's make the title of the blog post visually editable.

Retrieve Post ID

The first thing we need is to be able to map the content to ID values in Contentful. To ensure that data is coming back, add support for the [sys.id](http://sys.id) property in the GraphQL fields config in lib/api.js.

// lib/api.js

// Add sys.id field
const POST_GRAPHQL_FIELDS = `
sys {
  id
}
// other fields ...
`

Add ID Annotation to the Post

With annotations, we open up the editing context to a particular element using the data-sb-object-id attribute, with the value set to the item's ID.

This attribute should be placed on an element that encompasses (is a descendant of) the other elements that will be edited. In this case, let's add it to the <article> tag that surrounds the post content in pages/posts/[slug].js. (Note: This should be around line 30.)

// pages/posts/[slug].js

<>
  <article data-sb-object-id={post.sys.id}>/* ... */</article>
  // ...
</>

Learn more about annotations.

Annotate Post Title

Now let's annotate a particular element. You can make the title editable by adding the data-sb-field-path attribute to the <h1> element in the components/post-title.js component

export default function PostTitle({ children }) {
  return (
    <h1
      // Add the annotation for title
      data-sb-field-path="title"
      className="mb-12 text-6xl font-bold leading-tight tracking-tighter text-center md:text-7xl lg:text-8xl md:leading-none md:text-left"
    >
      {children}
    </h1>
  )
}

Test It!

Without needing to reload the page, you should now be able to highlight the title, edit it, and see the content updated in Contentful!

In-context visual editing with Stackbit is complete

Now, let's try the other direction:

Update the title in Contentful and our visual editor will update the page automatically, flicker-free. This is achieved by Automatic Content Reload.

Automatic Content Reload in action