Cover image for Add a Contentful blog to your NextJS app and Typescript

Add a Contentful blog to your NextJS app and Typescript

Contenful
NextJS
React

November 10, 2022

Cover image for Add a Contentful blog to your NextJS app and Typescript

Learn how to add a blog page to your existing NextJS React app using Contentful, React, Typescript, GraphQL code generator and urql

1. Prerequisites

  • Have a Contenful account

  • Have a Contenful "space" created

  • Have a "Blog" model created in the space

2. Get the Contentful access tokens

You need the SpaceId, the Content Delivery Access Token and the Content Preview Token

On your Contenful account click on Settings > API Keys

Then Click on Add Api Key

Copy the SpaceId, the Content Delivery Access Token and the Content Preview Token

Add the tokens to your .env file

CONTENTFUL_SPACE_ID=your Space ID
CONTENTFUL_ACCESS_TOKEN=Content Delivery API token
CONTENTFUL_PREVIEW_ACCESS_TOKEN=Content Preview API token 

3. Setup GraphQL codegen

Install graphql-codegen

First install graphql-codegen dependencies to automatically generate types from the Contentful GraphQL Schema

npm install --save graphql
npm install --save-dev @graphql-codegen/cli

Auto Let's graphql-codegen to setup everything by simply running the following command

npx graphql-codegen init

It should ask some questions so it can generate the file codegen.ts

For the following questions enter:

Where is your schema?: (path or url) https://graphql.contentful.com/content/v1/spaces/1234

Change 1234 with your spaceId

Where are your operations and fragments?: "pages/**/*.tsx","components/**/*.tsx"

Here I am going to read the graphql queries from the pages and the components

This is what I answered for the other questions:

After this, we should see the codegen.ts file has been created.

Now, install the required dependencies that were added to the package.json by the wizard

npm install

Next, we need to change the codegen.ts file so it can connect to the Contentul graphql with authentication. We are going to read this from the env variables. Change the file like this:

import type { CodegenConfig } from "@graphql-codegen/cli";
import { loadEnvConfig } from "@next/env";

const dev = process.env.NODE_ENV !== "production";
loadEnvConfig("./", dev).combinedEnv;

const CONTENTFUL_SPACE_ID = process.env.CONTENTFUL_SPACE_ID;
const CONTENTFUL_PREVIEW_ACCESS_TOKEN =
  process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN;

const config: CodegenConfig = {
  overwrite: true,
  schema: [
    {
      [`https://graphql.contentful.com/content/v1/spaces/${CONTENTFUL_SPACE_ID}`]:
        {
          headers: {
            Authorization: `Bearer ${CONTENTFUL_PREVIEW_ACCESS_TOKEN}`,
          },
        },
    },
  ],
  documents: ["pages/**/*.tsx", "components/**/*.tsx"],
  generates: {
    "src/gql/": {
      preset: "client",
      plugins: [],
    },
  },
};
export default config;

Generate needed node

Generate some code we need BEFORE writing our first query Run the command

npm run codegen

You should see a new folder called gql has been created along with some files inside it.

You can see the typescript types have been generated for the Contentful schema

Add a graphql query

Let's add a query to get all the blog titles.

Create a new page called blogs.tsx

In this page add the the following query. This is a simple query that will return all the blog titles

const blogListForHome = graphql(`
  query blogListForHome {
    blogCollection(order: date_DESC) {
      items {
        title
      }
    }
  }
`);

Run the code generator command to generate the types for this query

npm run codegen

4. Install urql

Run the command

npm install urql
Setup urql

Create the file urqlClient.ts

Add the following code to setup the urql client

import { createClient } from "urql";

export const client = createClient({
  url: `https://graphql.contentful.com/content/v1/spaces/${process.env.CONTENTFUL_SPACE_ID}`,
  fetchOptions: {
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${
        process.env.CONTENTFUL_PREVIEW
          ? process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN
          : process.env.CONTENTFUL_ACCESS_TOKEN
      }`
    }
  }
});

5. Fetch data and render in the page

Add the getStaticProps function to get the data from Contenful

Render the data

type Props = {
  blogCollection: BlogCollection;
};
const BlogPage = ({ blogCollection }: Props) => {
  return (
    <div>
      <ul>
        {blogCollection.items.map((el, idx) => (
          <li key={idx}>{el?.title}</li>
        ))}
      </ul>
    </div>
  );
};

That's it.

Source code

https://github.com/xap5xap/contentful-next