Within this guide, you will learn how to access content that has been created within Contentful CMS and render it within a Next.JS 13+ page using App Router. For developers one useful thing about Contentful development is that its pretty easy to find code examples online to help you to hook everything up, however, there is a catch!

From my experience, the majority of these examples mainly focus on NextJS and the now older page router. This can be very annoying when you are in a rush and you need to get shit done, so I thought I'd change that!

Read on to get access to a simple step-by-step guide that contains everything you need to be aware of within this new world. Learn how the setup compares to the old way, the gotchas, as well as how to set everything-up in code and within the CMS. If this sounds good to you, read on 🔥🔥🔥

Contentful/NextJS 13 What You Need To Know

The first important thing to know about hooking up Contentful with NextJS 13 with App Router is that the code you need to write is different compared to previous versions of NextJS. This probably sounds obvious, however, its easy to accidently reference the wrong page event handler, or, use the wrong file name and then wonder why you encounter an error, so be warned!

NextJS app router expects your page components to live within the App folder . This is different compared to the page router, which expects you to add your page components within Page folder instead. Next, you can not use the older event handlers like getStaticProps, getStaticPaths, or, getServerSideProps within your app routed component. Instead you will need to make use of generateStaticParams.

In terms of the mechanism to get NextJS and Contentful to talk to each other, there is an interesting point to be quickly mentioned. There are two way to get data from the CMS, REST API/SDK, or, via GraphQL. Before 2023 I used to say that this choice didn't mattered that much.

If you only need to access CMS content and you rendered your pages using SSG, or, you had a one to one mapping from your content models to pages, REST API is a good way to access data from the CMS. If on the other hand, you needed to integrate data from multiple content models on the same page then using GraphQL makes more sense.

When Contentful launched live preview, this advice changed. Nowadays, if you are planning on using the Contentful Live Preview feature its best to get the data from the CMS using GraphQL. If you do not care about live preview you can use REST API, however, be aware that you are limiting your solutions future proofness. As live preview works best when you use GraphQL on your site! This article will assume you pick GraphQL...

Setting Up The Configuration

In order to access data from Contentful, you will need to add some Contentful specific config within your NextJS app. These steps are all pretty simple, install some packages, add some settings within next.config.mjs, and add some specific environment variables. First, lets start with the NPM packages that you will want to install, these are:

Next, you will need to add some config within next.config.mjs. The config you will need to add are twofold, the first one is to whitelist the Contentful domain so your images will render without being blocked by security, the other one is to whitelist the Contentful domain for API access by adding a CORS rule:

The final step is to add some environment variables so your app can authenticate with Contentful and access the correct data. I will cover the specific variables in detail later but for reference your env file should look like this:

Get The Data From Contentful

With these set-up tasks nailed, a sensible next step is to create some content models within Contentful. I won't go into too much detail about the step you need to follow within the CMS to create a content model within this guide as I've created a deep dive video that you can watch on this topic here. Instead, I'll show you what the models I will be using look like.

The site structure for this project will be a simple blog with a homepage and some blog posts. To keep things simple, I haven't created a specific content model for the homepage. The homepage within my sample site will read in data from the post models in order to render a list of the blogs on the homepage.

In the real-world, your models will obviously need to be designed to match the data required within your wireframes and designs! The code to access GraphQL and query Contentful is shown below:

This class is pretty big, so lets break each section down. The first thing to point out is that there are two functions that can be called to get data from the CMS,getPost and getAllPosts

  • getPost: Returns data about a single blogpost (this method will be called from the blog post component)
  • getAllPosts: Returns data on all posts created within the CMS (this method will be called from the homepage component)

When dealing with GraphQL, if you need to access the same data in multiple functions, its a good practice to define that items schema within an object so it can be reused.

Within this file, I've done that by creating an object called POST_GRAPHQL_FIELDS. The code within fetchGraphQL should be pretty self-explanatory. In order to get the data from the CMS, I need to write a query that includes the specific space ID I want to work with. Without passing authentication tokens within the header the request will be blocked. Finally, to get the data you need, add the query as JSON/GraphQL within the body!

Creating a Contentful/NextJs Homepage

To get started, first create a NextJs site. I won't cover how to create a blank NextJS site now as its well documented elsewhere, basically install the NextJS package via NPM and off you go.

To create the components/files that will render the homepage and the blog post within NextJS, create a folder called app in your project root if it does not exist. Your homepage will need to live within this folder and in order to get the routing to work, your homepage component will need to be called page.js. This is different to the page router, where the filename needed to be called index.js in order to work. The code to render the homepage looks like this:

If you want to create a single page, you can repeat this process where the filename will map to the route within the URL to access that page. If you want to create a nest URL, you can create a folder and within that folder, create a file called page.js to map a default route.

Creating a Contentful/NextJs Dynamic Route Page

If you want to create a single type of page like a contact us page, you can repeat this process. Each file you create, the filename will map to the route within the URL to access that page.

Creating a Contentful/NextJs Dynamic Route Page

Most sites will need to support more than a single URL nesting hierarchy. For each nested URL/segment within the URL you want to add, within your solution create a child folder under the app folder.

For each folder you create, the name of that folder will map to the URL required to access it. You can carry on nesting folders as much as you like. In order to route a browser to your component in code, simply create a file in each folder called page.js to map the default route.

Creating components to render pages with static URLs like the homepage in code is easy. As you know the URL required to access that page as you write the code you can set the filename easily.

This process works fine for static URLs but it will not work when you need to render a bunch of blogs. When dealing with blogs for example, you will not know the URLs upfront. To fix this routing challenge, you will need to create components that support dynamic routing instead.

Within NextJS dynamic URLs are easy to set-up. Within the app folder create a new folder called blog,news`, etc... This name should match the segment before the blog URL that you want site visitors to use to access that content.

Within that folder create another folder called [slug]. Its this folder that tells NextJS we are dealing with dynamic routing. Within the [slug] folder, create a file named 'page.js` (do not use index.js as you used to!).

This covers the basics of getting up and running with Contentful and App Router... Happy Coding 🤘