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
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.