Generate Types from Contentful
Tags: typescript, contentful
Published: 2021-08-12 06:41:59

I'm developing an app with [nextjs](https://nextjs.org/) and [Contentful](https://www.contentful.com/).

https://fetools.vercel.app/

I think I implemented the basic functionality. So it is time to set up Typescript dev environment for this app.

In this post, I will introduce you how to generate types from Contentful data model.
Actually, the steps are quite straightforward if you read the repo `carefully` and follow the steps `carefully`. 


{% github intercom/contentful-typescript-codegen %}


The steps are below.
Step1. Install packages
Step2. Add a script to package.json
Step3. Put tokens on `.env` file
Step4. Add `getContentfulEnvironment.js`
Step5. Run the command (from Step2)


### Step1. Install packages
This step is very easy.

If you didn't install packages for TypeScript, you would need the following.
```zsh
# yarn
$ yarn add -D typescript @types/react @types/react-dom @types/node 

# npm
$ npm i -D typescript @types/react @types/react-dom @types/node 
```


```zsh
# yarn
$ yarn add -D contentful-typescript-codegen contentful-management dotenv

# npm
$ npm i -D contentful-typescript-codegen contentful-management dotenv

```

### Step2. Add a script to package.json
This step is also easy.

If you use next.js, the last script may be `lint`. So, you just need add the below after the `,`
```json
"scripts": {
    "contentful-typescript-codegen": "contentful-typescript-codegen --output @types/generated/contentful.d.ts"
  }
```

Here is mine. Basically, we won't need to execute this after generating types, so the long name is totally fine, but I like a simple command, so I set `codegen` as a command.
This is totally up to you.
```json
 "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint src --ext .js",
    "format": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json,css}'",
    "codegen": "contentful-typescript-codegen --output @types/generated/contentful.d.ts"
  },
```

### Step3. Put tokens on `.env` file
This step isn't difficult but I took some time to generate types because I didn't read the instruction/readme carefully.

In this step, we need to generate a new token.

Login Contentful > Settings > API Keys

If you use Contentful, you have `Space ID`, `Content Delivery API - access token`, `Content Preview API - access token`, and `Environments & Environment Aliases`

What we need to set to generate Types is `Content management tokens`. I used Content Delivery API instead of that and got 403 error. I was like whyyyyyyyyyyy 🤬 🤬 🤬 lol.

I believe the most important thing in this post is to generate `Content management tokens` lol.

```zsh
AccessTokenInvalid: {
  "status": 403,
  "statusText": "Forbidden",
  "message": "The access token you sent could not be found or is invalid.",
  "details": {},
  "request": {
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpbz9p7dzp18k9k9gbdl.png)

After generating the token, you will need to add it to `.env` file.

```
CONTENTFUL_SPACE_ID=aaaaaa
CONTENTFUL_ACCESS_TOKEN=bbbbb
CONTENTFUL_ENVIRONMENT=master
NEXT_PUBLIC_GOOGLE_ANALYTICS=ccccc
CONTENTFUL_PREVIEW_TOKEN=ddddddd
CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN=eeeeee <- new!!!
```


### Step4. Add `getContentfulEnvironment.js`
getContentfulEnvironment.js needs three items from `.env`.
- CONTENTFUL_MANAGEMENT_API_ACCESS_TOKEN
- CONTENTFUL_SPACE_ID
- CONTENTFUL_ENVIRONMENT

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

// console.log('accessToken', process.env.CONTENTFUL_ACCESS_TOKEN);

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

  return contentfulClient
    .getSpace(process.env.CONTENTFUL_SPACE_ID)
    .then((space) => space.getEnvironment(process.env.CONTENTFUL_ENVIRONMENT));
};
```


Step5. Run the command (from Step2)
We are almost there.

Finally we need to run the command.

```zsh
# yarn
$ yarn codegen
# npm
$ npm run codegen
```

The command works properly, you will see `@types/generated/contentful.d.ts` under the root folder.

The following is mine.

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

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

export interface IFeToolsFields {
  /** Title */
  title: string;

  /** Thumbnail */
  thumbnail?: Asset | undefined;

  /** Link */
  link: string;

  /** Tag */
  tag?: string[] | undefined;

  /** Description */
  description?: string | undefined;

  /** Category */
  category: 'font' | 'html/css' | 'image' | 'js/ts' | 'other';
}
```

As I emphasized the very top, the process is very straightforward and easy if you read the instruction carefully. Hope you won't waste time like me 😜