Create a Next.js App with Contentful and Deploy It with ZEIT Now
Deploy your Next.js and Contentful app with ZEIT 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 a single command to ZEIT Now.
Next.js from ZEIT is a production-ready framework that helps you create fast React apps. 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.
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:
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.
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 App
Firstly, create a project directory and cd
into it like so:
mkdir my-nextjs-contentful-project && cd my-nextjs-contentful-project
Next, initialize your project, creating a package.json
file in the process:
npm init -y
Next, add the project dependencies:
npm i contentful next react react-dom
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({ content_type: contentType.sys.id }) if (entries.items) return entries.items console.log(`Error getting Entries for ${contentType.name}.`) } const [posts, setPosts] = useState([]) useEffect(() => { async function getPosts() { const contentTypes = await fetchContentTypes() const allPosts = await fetchEntriesForContentType(contentTypes[0]) setPosts([...allPosts]) } getPosts() }, []) return ( <> <Head> <title>Next.js + Contentful</title> <link rel="stylesheet" href="https://css.zeit.sh/v1.css" type="text/css" /> </Head> {posts.length > 0 ? posts.map(p => ( <Post alt={p.fields.alt} date={p.fields.date} key={p.fields.title} image={p.fields.image} title={p.fields.title} url={p.fields.url} /> )) : null} </> ) } export default HomePage
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.
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} /> </a> <div className="text"> <h2>{title}</h2> <h4>{date}</h4> </div> <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; } `}</style> </div> ) } export default Post
Now that your page and component files have been created, the next step will show you how to add an environment variable to the project.
Step 4: Adding Environment Variables
Add a now.json
file at the root of your project directory with the following code:
{ "build": { "env": { "CONTENTFUL_SPACE_ID": "@contentful_space_id", "CONTENTFUL_ACCESS_TOKEN": "@contentful_access_token" } } }
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 = { env: { SPACE_ID: process.env.CONTENTFUL_SPACE_ID, ACCESS_TOKEN: process.env.CONTENTFUL_ACCESS_TOKEN } }
The next.config.js
file provides access to environment variables inside your Next.js app.
Now, add the following build script to your package.json
file:
{ ... "scripts": { "build": "next build" } }
Next, you will make your API keys available to your app during local development by creating a .env.build
file.
Create a .env.build
file at the root of your project directory with the following code, adding your API keys where instructed:
CONTENTFUL_SPACE_ID=your-space-id CONTENTFUL_ACCESS_TOKEN=your-access-token
Lastly, to make your API keys available for cloud deployment, create two Now Secrets with the commands below:
now secrets add CONTENTFUL_SPACE_ID your-space-id
now secrets add CONTENTFUL_ACCESS_TOKEN your-access-token
With those steps out the way you are now able to run your app. You can develop your app locally using the following command:
next dev
Step 5: Deploying the App
With your app ready, it is time to deploy it using a single command:
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.