[Nuxt.js] Contentfulを使ったブログ作成の覚え書き

# 今回の題

Nuxt.jsとContentfulを使ってブログを作ったのでその備忘録です。
Contentfulに作成したマークダウン形式の記事を、Nuxtで取得するところまで書いています。

作成したブログ：

https://gentuki-blog.site/

## 対象読者

- Nuxt.jsの知識があり、Nuxt.jsでブログを作ろうとしている方
- ブログ記事をMarkdown形式で書きたい方
- 数あるヘッドレスCMSの中からContentfulを選んだ方

既に技術選定済みの方向けなので、Nuxt.jsとContentfulを選んだ理由やメリットなどは書きません。シンプルに手順のみです。

## 手順

### Contentful側の実装

#### サインアップ

以下から。
https://www.contentful.com/
![スクリーンショット 2021-09-03 2.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/474dc61d-6e65-037c-ada6-60cb3957e16d.png)

#### Content modelの作成

個人的に見慣れない単語だったのですが、Content modelはテーブルのようなものだと認識しておけばいいと思いました。

ヘッダーのContent modelを選択して遷移した先のページで作成します。
モーダルが出るので任意の名前をつけて作成します。
ここではブログの記事を管理するContent modelとして`BlogPost`と名付け作成しました。

![スクリーンショット 2021-09-03 2.22.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/20a1e6fd-8bc7-699b-0765-51199fe14bac.png)

#### fieldの作成

Content modelをテーブルとするならばfieldはカラムの役割をするものです。
ブログの構成要素である、本文や投稿日時、バナー画像など必要なものを定義していきます。

Content model作成後に開かれたモーダルのadd fieldをクリックします。

![スクリーンショット 2021-09-03 2.30.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/d9f6ceb0-c3a7-66ba-057b-5745596a98a4.png)

取り敢えず、タイトルのfieldを作りましょう。
textを選択します。

![スクリーンショット 2021-09-03 2.33.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/cdfd2243-9135-5600-7519-dc3f6204ad11.png)

`name`をtitleとして、`Short text, exact search`を選択。
`create and configure`をクリック。

![スクリーンショット 2021-09-03 2.49.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/10d821fa-fd0a-3981-0c58-02ee3224eff6.png)

切り替わった先のモーダルで`title`fieldにバリーデーションの設定をします。
ここでは、
`Required field`で必須項目にして、
`Unique field`で一意な項目にしておきます。
![スクリーンショット 2021-09-03 2.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/7d672b48-2b9d-6635-bed6-ab309e9a2647.png)

同じように本文のfieldも設定します。
textを選択し、`name`をbodyとして、`Long text, full-text search`を選択。
![スクリーンショット 2021-09-03 3.05.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/0f1bdb77-02c9-9f2c-4c76-6cda4c5da5bc.png)
この後の流れはタイトルの時と同じです。

あとは、自分が必要だと思うfieldを作ってみてください。


##### 適当な記事を書いてみる

ヘッダーのContentを選択して遷移した先のページに
`add Blog Post`と書かれたボタンがあると思うのでクリックして進みます。
設定したfieldを備えたエディターのある画面に遷移するので、適当にマークダウンで記事を書き、
右の`Publish`をクリックすれば記事の完成です。

![スクリーンショット 2021-09-03 3.19.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/f559d923-8c5b-9904-84c3-0f1639dbe8e4.png)

####APIキーを作成・取得

ヘッダーのsettingsを選択するとドロップダウンが開くので、その中にある`API Keys`を選択。
遷移先のページの右にある`Add API Key`をクリック。

`Space ID`と
`Content Delivery API - access token`
をコピーしておいてください。

![スクリーンショット 2021-09-03 4.39.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546124/0d965889-6ab5-d3b5-63d1-e74d11ed6c72.png)



### Nuxt側の実装

#### インストール

対象読者的に問題ないとは思いますが一応公式のリンクを。

https://nuxtjs.org/docs/2.x/get-started/installation

内容に従ってインストールしてください。
cssフレームワークやlintツールなどはお任せします。
ただ、 SSRを前提で書くのでRendering modeをUniversalにしておいてください。

#### ContentfulのSDKをインストールして設定

```terminal
npm install contentful
```

plugins/contentful.js を作成して以下のように。
asyncData内で

```js:plugins/contentful.js 
export default ({ env }, inject) => {
  const contentful = require('contentful')
  const client = contentful.createClient({
    space: env.CONTENTFUL_SPACE_ID,
    accessToken: env.CONTENTFUL_ACCESS_TOKEN
  })
  inject('client', client)
}
```

nuxt.config.jsのプラグインに追加。

```js:nuxt.config.js
  plugins: [
    '@/plugins/contentful'
  ]
```

#### 環境変数を設定

.envに先ほど取得したSPACE_IDとACCESS_TOKENをセットします。

```js:.env
CONTENTFUL_SPACE_ID=XXXXXXXXX
CONTENTFUL_ACCESS_TOKEN=XXXXXXXXX
````

nuxt.config.jsのenvプロパティでセット。

```js:nuxt.config.js
  env: {
    CONTENTFUL_SPACE_ID: process.env.CONTENTFUL_SPACE_ID,
    CONTENTFUL_ACCESS_TOKEN: process.env.CONTENTFUL_ACCESS_TOKEN
  }
```

### ブログ記事の取得

記事を取得してタイトルだけ表示してみました。

```vue:pages/index.vue
<template>
  <div>
    <ul>
      <li v-for="(item, index) in items">{{ item.fields.title }}</li>
    </ul>
  </div>
</template>
<script>
export default {
  async asyncData ({ $client }) {
    const entries = await $client.getEntries({
      content_type: 'blogPost'
    })
    const items = entries.items
    return { items }
  }
</script>

```

`content_type: 'blogPost'`のblogPostの部分はContent modelに割り振られた`CONTENT TYPE ID`というもので記事通りに作成していればこれで大丈夫です。
もし違うようであれば、contentfulのサイトへ行き、ヘッダーのContent modelから作成したContent modelを選択してください。遷移したページの右に`CONTENT TYPE ID`の項目があるのでそれに書き換えればOK。

以上です。

## 参考

https://www.contentful.com/developers/docs/javascript/tutorials/using-js-cda-sdk/#retrieving-entries-with-search-parameters