ヘッドレスCMSでお気軽APIアクセス

# はじめに

近年JAMStackとともに注目を浴びているヘッドレスCMS。
簡単に説明するとウェブ制作のデザイン部分を切り離し、コンテンツ制作・管理のみに特化したサービス。
日本語にすると「首なしCMS」(日本語にしなくてよい)。

現在、多くのサービスが存在し、それぞれ特徴がある。
APIを提供しているのは必須条件であるが、RestfulなのかGraphQLなのか。
またリッチコンテンツに関してもHTML,Markdown対応など。
どちらか一方、もしくは両方対応しているものもある。

これまでいくつかのサービスを使ってみたのでそのあたりをまとめて紹介したい。

# 前提条件

## APIについて

各CMSでプログラム言語用のライブラリ(サードパーティを含む)を公開しているものもあるが、直接APIを叩くことを基本とするためCurlを使った利用法を説明する。
またCRUDに関してはフリープランで利用制限がある場合もあるのでR(read)のみ、つまりコンテンツの取得のみを取り上げる。
書き込みに関しては読み込みとトークンを使い分ける場合もあるが、だいたい各CMS毎にパターンは似通っているのでドキュメントを参照して実行してもらえればよい。

## モデル設計

話を簡単にするため扱うモデルとしてはブログを対象とし、以下のスキーマをもつものとする。

* title: タイトル
* slug: スラグ(マルチバイト圏でははやらないけど必須とされることが多い)
* body(または content): 本文

その他ブログに必須項目である作成日や作成者という項目はシステム情報としてあらかじめ存在しているため今回は割愛する。

では早速紹介にうつろう。

# 特選CMS

## Contentful

https://www.contentful.com/

恐らく世界でもっとも多く使われているヘッドレスCMS。そのため情報量も多い。
コンテンツ作成は`space`と呼ばれるプロジェクトにモデルのスキーマを定義して行う。

![FireShot Capture 214 - こんにちは — Content — The example project — Contentful - app.contentful.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/3078cc29-9545-d49f-9017-95e381349e39.png)


APIキーの取得はダッシュボード>Settings>API Keys>Add API Keysで表示(発行)される以下を使う

* `Space ID`
* `Content Delivery API - access token`

上記の他にもあるが本例では使わない。

* `Content Preview API - access token`
* `Content management tokens`

環境変数をあらかじめ以下のように設定し(私の場合は.env)

```shell
ENDPOINT=https://cdn.contentful.com/spaces
SPACE_ID=<Space ID>
MODEL_ID=<自分の作成したモデルのID>
ACCESS_TOKEN=<上記のContent Delivery API>
```

実際のアクセスはこんな感じ

```shell
curl -s "${ENDPOINT}/${SPACE_ID}/entries?order=fields.title&content_type=${MODEL_ID}&access_token=${ACCESS_TOKEN}"
```
レスポンスが長くなるのでjqで整形するならこんな感じ

```shell
curl -s "${ENDPOINT}/${SPACE_ID}/entries?order=fields.title&content_type=${MODEL_ID}&access_token=${ACCESS_TOKEN}"|jq -r '.items[].fields.title,.items[].sys.createdAt,.items[].fields.body.content[].content[].value'
```

結果

```shell
こんにちは
2021-12-15T23:30:23.783Z
はじめまして。
どうぞよろしく。
お願いします。
```

モデルのフィールドにリッチテキストを使うとレスポンス構造が複雑になるのでライブラリなしで取り扱おうとするとはっきりいって死ぬ。

## microCMS

https://microcms.io/

国産ヘッドレスCMSの雄。
日本語のダッシュボードが親切というだけでなく直感的に使えるユーザインターフェースがいい。

サービスと呼ばれるプロジェクトを生成し、モデルに相当するものはAPIと呼ばれる。

![FireShot Capture 216 - 管理画面 - microCMS - hige-sample.microcms.io.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/985fb599-4d3f-24f9-7d4e-d252cae9f3f1.png)

Markdown自体での入力はできるのだが自動的にHTMLに変換されるので使えるというのか微妙というのか。

APIを利用するにはエンドポイントとトークンが必要となる。

環境変数

```shell
SERVICE=<サービス名>
CONTENTS=<API名>
ENDPOINT=https://${SERVICE}.microcms.io/api/v1/${CONTENTS}
X-MICROCMS-API-KEY=<アクセストークン>
```

一覧取得

```shell
curl -s -X GET -H "X-MICROCMS-API-KEY : ${X-MICROCMS-API-KEY}" "${ENDPOINT}"
```

結果

```json
{"contents":[{"id":"xxxxxx","createdAt":"2021-12-13T03:16:08.353Z","updatedAt":"2021-12-16T04:40:04.410Z","publishedAt":"2021-12-13T03:16:08.353Z","revisedAt":"2021-12-16T04:40:04.410Z","title":"初めての投稿","slug":"first-post","body":"こんにちはハロー","content":"<h1 id=\"xxxx\">こんにちは</h1><ul><li>ほげ</li><li>ふが</li></ul><p><br><img src=\"https://images.microcms-assets.io/assets/x/xxxx/android-chrome-192x192.png\" alt=\"\"></p>"}],"totalCount":1,"offset":0,"limit":10}
```

実行にはAPIプレビューと呼ばれる機能があるのでわざわざcurlなどでアクセスしなくてもよい。

## GraphCMS

https://graphcms.com/

その名の通りGraphQLを用いたAPIアクセスが売り。
以前投稿した[GraphCMSとHugoを連携してGithub Pagesで公開する(3)〜PythonでGraphQLを実行](./2b1b3171854469a9c4a8)にかなり詳細に書いているのでここでは割愛する。

APIの利用に必要なエンドポイントとトークンは独自物のが発行される。
あと、パーミッションを適切に設定しないと権限不足でエラーになる場合がある。

環境変数

```shell
ENDPOINT=<Content APIと呼ばれるエンドポイント>
TOKEN=<Permanent Auth Tokensというトークン>
```
一覧取得

```shell
curl -X POST ${ENDPOINT} \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"query":"{posts {title slug body}}"}
```

結果

```json
{"data":{"posts":[{"title":"はじめての投稿","slug":"hello","body":"ようこそ\n"}]}}
```

こちらもAPI PlaygroundとよばれるAPIの実行環境が管理画面から利用できるのでプログラムに落とし込む前に動作確認ができる。
というよりむしろ利用しないと開発効率が悪い。

![FireShot Capture 220 - GraphCMS - app.graphcms.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/cec08f47-4b1f-ef8f-8caf-f9cf5967b8c7.png)


## DatoCMS

https://www.datocms.com/

microCMS同様、ウェブのダッシュボードが洗練されている。
こちらはProjectと呼ばれるプロジェクトを作成してモデルと呼ばれるModelを定義する。そのままなのでわかりやすい。

![FireShot Capture 219 - Models - post - qiita-sample - Dato CMS - qiita-sample.admin.datocms.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/ad49ca9c-8ed4-9d2d-066b-6c81414f6c29.png)

Restful APIとGraphQLの両方に対応している。
API Explorerとよばれる機能を使うとお手軽にGraphQLが実行できる。

環境変数

```shell
ENDPOINT=https://site-api.datocms.com
TOKEN=<トークン>
```

トークンはRead-only API tokenとFull-access API tokenがあるが、本例では前者でよい。

一覧取得

```shell
curl -X GET ${ENDPOINT}/items \
-H "X-Api-Version: 3" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer ${TOKEN}"
```

結果

```json
{"data":[{"id":"123456","type":"item","attributes":{"title":"こんにちは","slug":"hello","body":"こんにちはみなさん。\n","updated_at":"2021-12-16T06:30:19.999+00:00","created_at":"2021-12-16T06:30:19.994+00:00"},"relationships":{"item_type":{"data":{"id":"123456","type":"item_type"}},"creator":{"data":{"id":"31426","type":"account"}}},"meta":{"created_at":"2021-12-16T06:30:19.994+00:00","updated_at":"2021-12-16T06:30:19.999+00:00","published_at":"2021-12-16T06:30:20.011+00:00","publication_scheduled_at":null,"unpublishing_scheduled_at":null,"first_published_at":"2021-12-16T06:30:20.011+00:00","is_valid":true,"status":"published","current_version":"123456","stage":null}}],"meta":{"total_count":1}}
```

## CosmicJS

https://www.cosmicjs.com/

はっきり言って少しくせがある。
Projectsの中にBucketと呼ばれるプロジェクトのようなものを作ってObjectと呼ばれるモデルを設計するのだが、デフォルトで推奨されるslugとcontentsというフィールド作成を無視するとよくわからないエラーに悩まされる。
しかしReactやVueなどのアプリを簡単に作れることは特筆すべきかと思う。

![FireShot Capture 221 - Create Bucket - Cosmic - app.cosmicjs.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691494/35022130-eee1-0e04-04ff-cb29b13f0d5b.png)

環境変数

```shell
ENDPOINT=https://api.cosmicjs.com/v1/
BUCKET_SLUG=<Bucketのスラグ>
READ_KEY=<読み込み用のキー>
WRITE_KEY=<書き込み用のキー>
```

一覧取得

```shell
curl -s -X GET "${ENDPOINT}${BUCKET_SLUG}/objects?read_key=${READ_KEY}
```

なお、APIは v2(https://api.cosmicjs.com/v2/) もあるため、ドキュメントをよく読まないとはまる

## Prismic

https://prismic.io/

Restful APIとGraphQLに対応

* [Introduction to the Prismic Content Query API with Rest API \- Prismic](https://prismic.io/docs/technologies/introduction-to-the-content-query-api)
* [Integrating Prismic's GraphQL API with an existing Javascript Project \- Prismic](https://prismic.io/docs/technologies/integrate-with-existing-js-project-graphql)

こちらはまずrefと呼ばれるものを取得する必要がある

```shell
curl https://<自分のプロジェクト名>.prismic.io/api/v2
```

上記のレスポンス

```json
{
  "refs": [
    {
      "id": "master",
      "ref": "hogehogehoge",
      "label": "Master",
      "isMasterRef": true
    }
```

`hogehogehoge`がrefなので環境変数を以下のように設定

```
ENDPOINT=https://<自分のプロジェクト名>.prismic.io/api/v2
REF=hogehogehoge
ACCESS_TOKEN=xxxxxx
```

一覧取得

```shell
curl ${ENDPOINT}/documents/search?ref=${REF}&access_token=${ACCESS_TOKEN}
```

# 総評

サービスの継続性や利用者の多さから言うと迷ったらContentfulを使うのが無難。
対抗場はmicroCMSか。日本語ベースというだけでなくサービスの改善が頻繁に行われているのでだんだん利用しやすくなってきている。

個人的に好きなのはGraphQL。無料区分で使えるAPIコール数が多いのとまたレスポンスで返すJsonのフォーマットがシンプルなので扱いやすいからだ。

使ったことあるけども今回紹介しなかったものとしては[Forestry](https://forestry.io/)。
あと[Strapi](https://strapi.io/)はオンプレで運用することができるタイプ。
他のオンプレ運用の選択肢でいうとWordPressのヘッドレス化がある。

その他にも[microCMS開発者の柴田さんの記事](https://codezine.jp/article/detail/15054)にもいくつか紹介されている。
この記事では今回割愛したヘッドレスCMSのきちんとした説明が書かれているので興味があれば一読していただきたい。