How To Build a Powerful Blog Using Next.js & Contentful
Liran Glikman, Mon Oct 19 2020, 7 min
Dev life at Oribi is very interesting. We tackle a lot of engineering challenges such as new technologies, complex systems, ever-increasing scale and so much more...
As we evolve, we gather a lot of useful experience. It occurred to us that we should share this, in an attempt to hopefully help others who face the same challenges.
So we decided to create our very own tech blog. In this post, I will explain what we did and how we created the site. We’ll cover the technologies we used and how we made sure it would be scalable and fast.
So let’s get started.

The Tech Stack

From the start, we knew we had to follow these guidelines:
  1. Use modern technologies.
  2. Maintain great site performance.
  3. Adding new posts should be as easy as possible.
After some thought and research, we decided to create the site using React and Next.js. For content management we chose Contentful.

Next.js

Next.js is a React framework that simplifies the creation of modern web applications, keeping great performance in mind. Also, it is well supported around the Internet because it is used by many major tech companies.
One of the features that led us to choose Next.js is its SSG, or Static Site Generation capabilities.
Since the early days of AngularJS and later Angular and React, we had been used to client-side rendering, which works as follows:
Client-side rendering is a good fit for single-page applications and complex products, but SSG is a much better fit for content-based websites with multiple pages.

Let’s delve further into SSG. With it, we prerender the pages at build time, which results in a single HTML file (for each page) that contains all of the relevant data! 
This means no multiple HTTP requests and no loading. All of the pages are ready as soon as the initial request is resolved, which results in fast performance and less logic on the client side.

In addition to that, because we get all of the page’s content in a single HTML file with a single request, the website’s SEO is improved with no extra effort, as the content will always be available.

Contentful

Contentful is a CMS tool that lets us store content and easily fetch it using a friendly API.
Contentful has a lot of really powerful features that we like:
  1. We can create content models to match our requirements. For example, we can create a post model with a title property, a date property, and much more…
  2. It features a powerful rich text editor that lets us edit and view content inside the Contentful UI.
  3. We can embed models inside other models for powerful combinations. For example, we can create a code snippet model with code examples and embed this inside the blog post model.
Contentful has many additional features like a staging environment and much more. you can read about it here.

Setup


Configure Contentful

Let’s start by signing up for Contentful. After that, we’ll create our first space. Everything related to the blog should be within this single space. So let’s go to the Content Model tab and create our post entity. It should look something like this:
A few things to notice:
  • The slug property is the post’s URL on the website.
  • The content property is a rich text editor that allows us to write anything in it.
Next, we save this model and go to the Content tab, where we will be able to create a new post entity and write our first post.
Last but not least, we need to go to the Settings tab and then to API Keys, in order to generate a private key that will be used later in our application.

Configure Next.js

The time has come to finally create our website. To do so, we can begin by following the official Next.js instructions, which explain everything we need to start, from downloading the necessary packages to configuring the build process.
Once the installation process is done, we will have a solid project structure and a simple website up and running.
Before proceeding, I recommend at this point to install the following NPM packages:

The setup process is finally over and now we can get to the fun part!

Let’s Write Some Code


Creating the Home Page

The home page should contain a list of all of the available posts. Each element in that list should be a link that will navigate the user to the selected post page. 
Let’s start by creating an index.jsx file inside the pages folder. Remember, Next.js creates an HTML file for each file in the pages folder. The index file will map to the root path on our website.
A basic page should look like this:
import React from 'react';

const TechBlog = () => {
  return (
    <div>
      HELLO WORLD
    </div>
  );
};

export default TechBlog;

Next, let’s add a JavaScript file to hold the Contentful integration logic. In it, we will create a new function that will fetch all of the available posts from Contentful.
Note: here we should use the Contentful API key that we generated in the previous step.
import { createClient } from 'contentful';

export async function getAllBlogPosts() {
  const client = createClient({
    space: '<Contentful space token>',
    accessToken: '<API private key>',
  });

  const entries = await client.getEntries({
    content_type: 'post',
  });

  return entries?.items?.map(item => {
    const fields = item.fields;
    return {
      title: fields.title,
      slug: fields.slug,
      content: fields.content,
    };
  });
}

Now, it’s time to integrate this function onto our home page. To do so, we are going to use Next.js’s SSG feature, which will fetch the posts at build time instead of on the client side. To do this let’s add a new function to the index.jsx file called getStaticProps. It will look like this:
export const getStaticProps = async () => {
  const posts = await getAllBlogPosts();

  return {
    props: { posts },
  };
};
Next.js automatically detects pages with the getStaticProps function in them and renders them at build time, by creating a complete HTML file with all of the relevant data. Data from the props object is returned and all that is left for us to do is to add the posts object to the TechBlog component’s props like this:
import React from 'react';
import Link from 'next/link';

const TechBlog = ({ posts }) => {
  return (
    <div>
      <ul>
        {posts.map((post => (
          <li>
            <Link as={`/${post.slug}`} href={`/[slug]`}>
              <a>{post.title}</a>
            </Link>
          </li>
        )}
      </ul>
    </div>
  );
};

export default TechBlog;
Note: Next/Link is a Next.js component for faster navigation between pages.

That’s it! We just created a home page containing a list of blog posts taken from Contentful. Each item in the list is a link to its respective blog post.

To view the generated HTML file, all we need to do is run the following command:
next build && next export
A new folder will be created called out and inside of it all of the generated HTML files will be stored.

Creating a Single Post Page

Creating a post page isn’t so different from creating the home page: we fetch the post from Contentful using SSG, pass it into the Post component and render it.
However, there are some differences, which we will go over now.
First, let’s create a new function to fetch a single post from Contentful with a specific slug:
export async function getSingleBlogPost(slug) {
  const client = createClient({
    space: '<Contentful space token>',
    accessToken: '<API private key>',
  });

  const entry = await client.getEntries({
    content_type: 'post',
    limit: 1,
    'fields.slug[in]': slug,
  });

  return entry?.items?.map(item =>{
    const fields = item.fields
    return {
      title: fields.title,
      slug: fields.slug,
      content: fields.content,
    };
  })[0];
}

Next, each blog post page should have a unique URL which means that unlike the index.jsx file inside the pages folder, we need dynamic routes. So let’s create a new file called [slug].jsx, and in it, a function called getStaticPaths:
export const getStaticPaths = async () => {
  const posts = await getAllBlogPosts();
  const paths = posts?.map(({ slug }) => ({ params: { slug } })) ?? [];

  return {
    paths,
    fallback: false,
  };
};
When Next.js detects a file with [<name>] and the getStaticPaths function in it, it will run it at build time and generate a new HTML file for each path in the paths list. In our example, we will fetch all of the blog posts and will create an HTML file for each post with the slug property as its name.

Next, we will add a getStaticProps function as follows to pass the needed data for each page:
export const getStaticProps = async (context) => {
  const { slug } = context.params;
  const post = await getSingleBlogPost(slug);

  return {
    props: { post },
  };
};
Here you can see that the function runs for each dynamic file, and it gets that file’s context as a property which includes the file’s name. 

Finally, let’s create a post component as follows: 
import React from 'react';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';

const Post = ({ post }) => {
  return (
    <div>
      <h2>{post.title}</h1>
      {documentToReactComponents(post.content)}
    </div>
  );
};

export default Post;

And that’s it! A unique HTML file for each blog post is created, containing the post title and its content fully rendered.

Summary

After finishing the steps above, it's time to celebrate our achievement! We have created a fully functioning blog website with content integration and fast performance.
All that is left to do is to deploy it live and start writing awesome content! Once new content has been added to Contentful, just make sure to rebuild and redeploy.
I hope that I managed to help you get started with Next.js & Contentful and maybe even with creating your very own blog. See you again in future posts.
Let’s start blogging!
We’re Hiring!
Oribi is growing,
come join our amazing team :)
Check out our Careers Page