Generate Typings From Your Contentful Environment In A Next.js Project

Generate Typings From Your Contentful Environment In A Next.js Project

Ummar Hamid's photo
Ummar Hamid
·Nov 8, 2022·

4 min read

Table of contents

Introduction

In our last blog, we learned how to set up and implement the basic functionality while developing an application with Next.js and Contentful.

This time, we’ll introduce how you can generate Types from a Contentful data model. For this, we will be using contentful-typescript-codegen with TypeScript.

You can use this in your TypeScript applications to increase developer confidence and productivity. It also ensures that breaking changes to our Content Types don't cause an outage.

Let’s get started!

Step 1. Install Packages

Install the required packages by running the following:

yarn add -D contentful-typescript-codegen contentful-management dotenv

Step 2. Add The Required Script To Package.json

"scripts": {
   "generate-types": "contentful-typescript-codegen --output @types/generated/contentful.types.ts",
 }

Here’s what our package.json file looks like at this point:

package.json

"scripts": {
   "dev": "next dev",
   "build": "next build",
   "start": "next start",
   "lint": "next lint",
   "generate-types": "contentful-typescript-codegen --output @types/generated/contentful.types.ts"
 }

You won't need to execute this after generating Types, so any name is fine. We have used generate-types as a command. You can use something else.

Step 3. Get Your Tokens And Put Them On .env File

In this step, you’ll need to generate a new token.

Login Contentful > Settings > API Keys

image1.png image2.png image3.png

Keep your CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN handy. You will need to add it to your .env file

From Contentful, you should have your Space ID, Content Delivery API - access token, Content Preview API - access token, and Environments & Environment Aliases.

You will need to set the content management tokens to generate types.

After generating the token, add it to the .env file.

.env

NEXT_PUBLIC_CONTENTFUL_SPACE_ID=aaaaaa
NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN=bbbbb
NEXT_PUBLIC_CONTENTFUL_ENVIRONMENT=master
NEXT_PUBLIC_CONTENTFUL_HOST=preview.contentful.com
NEXT_PUBLIC_CONTENTFUL_CONTENT_MANAGEMENT_TOKEN=eeeeee <- new!!!

Step4. Add getContentfulEnvironment.js

getContentfulEnvironment.js needs three items from .env:

  • CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN
  • CONTENTFUL_SPACE_ID
  • CONTENTFUL_ENVIRONMENT

getContentfulEnvironment.js in project root directory

require('dotenv').config();
const contentfulManagement = require('contentful-management');

module.exports = function () {
 const contentfulClient = contentfulManagement.createClient({
   accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_CONTENT_MANAGEMENT_TOKEN,
 });

 return contentfulClient
   .getSpace(process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID)
   .then((space) =>
     space.getEnvironment(process.env.NEXT_PUBLIC_CONTENTFUL_ENVIRONMENT),
   );
};

Step5. Run The Command (from Step2)

We are almost there. You will need to run the command.

yarn generate-types

If the command works properly, you will see:

@types/generated/contentful.types.ts under the root folder. The following is what's generated in our case.

contentful.types.ts

// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY IT.

import { Asset, Entry } from 'contentful';
import { Document } from '@contentful/rich-text-types';

export interface ICategoryFields {
 /** Image */
 image: Asset;

 /** Title */
 title: string;
}

/** Basic content type for defining various categories of products available within Grocery Plus */

export interface ICategory extends Entry<ICategoryFields> {
 sys: {
   id: string;
   type: string;
   createdAt: string;
   updatedAt: string;
   locale: string;
   contentType: {
     sys: {
       id: 'category';
       linkType: 'ContentType';
       type: 'Link';
     };
   };
 };
}

export interface IProductFields {
 /** Images */
 images: Asset[];

 /** Description */
 description: string;

 /** summary */
 summary?: string | undefined;

 /** unit */
 unit: string;

 /** quantity */
 quantity: number;

 /** price */
 price: number;

 /** discount */
 discount?: number | undefined;

 /** category */
 category?: ICategory | undefined;
}

/** Basic model for an individual product for Groceries-plus */

export interface IProduct extends Entry<IProductFields> {
 sys: {
   id: string;
   type: string;
   createdAt: string;
   updatedAt: string;
   locale: string;
   contentType: {
     sys: {
       id: 'product';
       linkType: 'ContentType';
       type: 'Link';
     };
   };
 };
}

export interface IUsersFields {
 /** name */
 name: string;

 /** contact */
 contact?: number | undefined;

 /** address */
 address?: string | undefined;

 /** avatar */
 avatar?: Asset | undefined;
}

/** content type for storing user data for user profiles */

export interface IUsers extends Entry<IUsersFields> {
 sys: {
   id: string;
   type: string;
   createdAt: string;
   updatedAt: string;
   locale: string;
   contentType: {
     sys: {
       id: 'users';
       linkType: 'ContentType';
       type: 'Link';
     };
   };
 };
}

export type CONTENT_TYPE = 'category' | 'product' | 'users';

export type LOCALE_CODE = 'en-US';

export type CONTENTFUL_DEFAULT_LOCALE_CODE = 'en-US';

Read the instructions carefully, and you’ll notice how straightforward and easy the entire process is.

Conclusion

In this five-step guide, we learned how to generate types for our content from a Contentful environment in a Next.js project. We hope you found it helpful! Don’t forget to share your thoughts in the comments.

 
Share this