Create a Next.js and Contentful Application That Builds and Deploys with Now

How to deploy your Next.js and Contentful application with Now in a serverless environment

In this guide, you will discover how to create a Next.js app that displays links to posts from the ZEIT blog by utilizing the Contentful client, before deploying with just a single command to ZEIT Now.

Next.js from ZEIT is a production-ready framework that helps you create fast React applications. Contentful is a powerful headless CMS that allows you to rapidly create, manage and distribute content to any platform you like.

By following this guide, you will create a clone of the example app, a starting point to get you up and running with your own Next.js + Contentful app in minutes.

Step 1: Create your Contentful Content

From your Contentful Spaces dashboard, create a new Content Model called Post by clicking the Add content Type button.

Creating a Content Model for your Next.js + Contentful project using the Contentful dashboard.

Add the following fields to your Content Model, all of type Short Text, by clicking the Add field button:

  • title
  • date
  • alt
  • image
  • url

Your Post Content Model should look like this:

An example Content Model for your Next.js + Contentful project.

Next, using the Content tab, click the Add Post button to create a post, providing the relevant details.

That's it for creating content! You can edit both the Content and Content Model at any time, giving you complete flexibility over your content.

Next, you will create a set of API keys for use in your app, this will allow you to connect to the Contentful Client to request your posts.

Step 2: Creating API keys

Click the Settings tab and choose the API Keys option, then click the Add API Key button.

Note: Use separate keys for each platform you need to deliver content to.

With the keys created, make a note of both the Space ID and the Content Delivery API - access token, these will be used later on.

That's all the setup required for Contentful, within just a few minutes you have managed to create a Content Model, add content and generate a set of API keys.

In the next step, you will create your Next.js app.

Step 3: Creating your Next.js Application

Firstly, create a project directory and cd into it like so:

mkdir my-nextjs-contentful-project && cd my-nextjs-contentful-project

Creating and entering into the project directory.

Next, initialize your project, creating a package.json file in the process:

yarn init -y

Initializing your project with a package.json file.

Note: Using the -y flag will initialize the created package.json file with these default settings.

Next, add the project dependencies:

yarn add contentful next react react-dom

Adding contentful, next, react and react-dom as dependencies to your project.

With the project initialized, create a /pages directory with a index.js file inside that uses the following code:

import { useEffect, useState } from 'react'
import Head from 'next/head'
import Post from '../components/post'

const client = require('contentful').createClient({
  space: process.env.SPACE_ID,
  accessToken: process.env.ACCESS_TOKEN

function HomePage() {
  async function fetchContentTypes() {
    const types = await client.getContentTypes()
    if (types.items) return types.items
    console.log('Error getting Content Types.')
  async function fetchEntriesForContentType(contentType) {
    const entries = await client.getEntries({
    if (entries.items) return entries.items
    console.log(`Error getting Entries for ${}.`)
  const [posts, setPosts] = useState([])
  useEffect(() => {
    async function getPosts() {
      const contentTypes = await fetchContentTypes()
      const allPosts = await fetchEntriesForContentType(contentTypes[0])
  }, [])
  return (
        <title>Next.js + Contentful</title>
      {posts.length > 0
        ? => (
        : null}

export default HomePage

An example index.js page for your Next.js + Contentful project.

Let's take look at what this file achieves.

Firstly, it requires the contentful dependency and creates a client, this provides access to many useful helper methods for retrieving content from Contentful.

Inside the HomePage function, two asynchronous functions are defined, these are then called in the useEffect hook to retrieve the posts on initial load.

Note: These functions are simplified versions taken from the Contentful JavaScript Boilerplate.

With the posts retrieved, they are then mapped over to be displayed with a <Post> component that you will create next.

Create a /components directory that contains a post.js file with the following content:

function Post({ alt, date, image, title, url }) {
  return (
    <div className="container">
      <a href={url}>
        <img alt={alt} src={image} />
      <div className="text">
      <style jsx>{`
        .container {
          cursor: pointer;
          height: 453px;
          margin-bottom: 48px;
        a {
          border-bottom: none;
        a:hover {
          border-bottom: none;
        .text {
          margin-top: -160px;
          padding: 24px;
          position: absolute;
        h2 {
          color: white;
          font-size: 24px;
          margin-bottom: 0;
        h4 {
          color: rgba(255, 255, 255, 0.8);
          font-size: 16px;
          font-weight: 500;
          margin-top: 8px;

export default Post

An example post.js component for your Next.js + Contentful project.

Now that your page and component files have been created, the next step will show you how to use the now.json file to allow for both local development and cloud deployment.

Step 4: Adding a now.json File

With your project ready, the now.json file provides an opportunity to instruct Now on how to build and deploy your project. Add a now.json file at the root of your project directory with the following code:

  "version": 2,
  "builds": [{ "src": "package.json", "use": "@now/next" }],
  "build": {
    "env": {
      "SPACE_ID": "@space_id",
      "ACCESS_TOKEN": "@access_token"

An example now.json file for your Next.js + Contentful project.

The above now.json file achieves three things:

With your now.json file created, you should add a next.config.js file at the root of your project directory with the code below:

module.exports = {
  target: 'serverless',
  env: {
    SPACE_ID: process.env.SPACE_ID,

An example next.config.js file for your Next.js + Contentful project.

The next.config.js file achieves two things:

  • It tells Next.js to build for a serverless environment
  • Provides access to environment variables inside your Next.js app

Next, you will make your API keys available to your application during local development by creating a file.

Create a file at the root of your project directory with the following code, adding your API keys where instructed:


An example file for your Next.js + Contentful project.

Lastly, to make your API keys available for cloud deployment, create two Now Secrets with the commands below:

now secrets add SPACE_ID your-space-id

Adding the SPACE_ID secret to your project using Now Secrets.

now secrets add ACCESS_TOKEN your-access-token

Adding the ACCESS_TOKEN secret to your project using Now Secrets.

With those steps out the way you are now able to run your application. You can develop your application locally using the following command:

now dev

Using the now dev command to simulate the Now deployment environment locally.

By using now dev, you are able to run your application locally, in a reproduction of the Now deployment environment. This ensures there are no surprises when you deploy your app.

Step 5: Deploying the Application

With your application ready, it is time to deploy it using just a single command:


Using the now command to deploy your project to Now.

You will see a short build step in your terminal followed by the news that your project has been deployed, it should look similar to the example app.


For more information on working with Contentful and Next.js, please refer to their documentation.

To configure Now further, please see these additional topics and guides:

Written By
Written by msweeneydevmsweeneydev
on June 18th 2019