【Hugo】GitHubをヘッドレスCMSとして使ってみる

こんにちは。

今回はGitHubをHugoのCMSとして活用してみました。

Hugo + Headless CMS

このブログではHugoをSSGとして利用しています。

新しく記事を執筆するときは、執筆環境にサイト管理用のリポジトリやVSCode、Hugoを用意してから執筆することになります。

この作業は一度やれば済むので、別にそこまで辛くはないのですが、問題は画像を配置するときです。

VSCodeを使って執筆している時に、新規に画像を追加すると以下の手順が発生します。

1
スクリーンショットを保存→imagesディレクトリに配置→ショートコードを書く

これを画像を追加するたびに行うのは非常に面倒です。

そこで、ヘッドレスCMSの登場です。これを利用すれば、QiitaやZennのようにクリップボードにある画像をそのまま配置できたり、画像をWordPressのように管理できたりします。

Hugoと相性の良いヘッドレスCMSを検索してみるとForestryやNetlify CMSなどがヒットします。 しかしながら、ForestryはTina CMSというプロジェクト変わっていたり、Netflify CMSはデプロイ先が限られたりとやや面倒そうです。

実際にTina CMSについては使用してみましたが、 UIが好みではなく、設定についてもやや限られている印象でした。(私が使いこなせてない可能性も大いにありますが…)

私は欲しいヘッドレスCMSは以下のような特徴を持つものです。

  • DBMSを必要としない
  • いつでも執筆環境にアクセスできる
  • ノーコストで運用ができる

GitHubという選択肢

みなさんご存知の通り、GitHubのIssueには優秀なMarkdownエディタがあります。 このエディタはクリップボードにある画像も貼り付けることができます。 そして、GitHubはAPIを提供しており、GitHub上のデータを自由に利用できます。

ということで、CMSに必要なフロント部分としてGitHubを活用し、記事の生成部分を自分で作ります。

作ったもの

https://github.com/rokuosan/github-issue-cms

今回作成したものは、GitHub上のIssueを記事として扱います。 実行時にCloseされているIssueの最初のコメントを記事のコンテンツとしてファイルに保持します。

タグやカテゴリについては、それぞれラベルとマイルストーンが対応します。

既存のHugoプロジェクトに組み込む

今回作成したものは、CIに組み込むことを想定しています。この記事の場合、データをすべてGitHub上に保管しており、CIとしてGitHub Actionsを利用しました。

GitHub Actionsで利用する際に、Issueへのアクセス権を持ったトークンを発行しておきます。 発行したトークンをブログを管理しているリポジトリのシークレットにGH_TOKENという名前で登録します。

最後に以下のようなワークフローを定義します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
name: Go

on:
  push:
    branches: [ "main" ]
  issues:
    types: [reopened, closed]
  pull_request:
    branches: [ "main" ]
  workflow_dispatch:

permissions: write-all

jobs:

  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21.4'

    - name: Install Tools
      run: go install github.com/rokuosan/github-issue-cms@latest

    - name: Generate
      run: github-issue-cms generate --token=${{ secrets.GH_TOKEN }}

    - name: Auto Commit
      uses: stefanzweifel/git-auto-commit-action@v4
      with:
        commit_message: "ci: :memo: Add new articles"

    - name: Clouflare Pages Webhook
      run: |
        curl -X POST ${{ secrets.CF_WEBHOOK_URL }}        

この例では、デプロイにCloudflare Pagesを利用しています。 そのためデプロイ時に利用するCloudflareのWebhook URLを、シークレットに登録しておき、ジョブの最後にPOSTするようにしています。

image

Issue を書く

ワークフローを登録しているリポジトリで、Issueを書きます。

この時に、ラベルとマイルストーンを利用すれば、それぞれタグとカテゴリを設定することができます。

また、Issueの先頭にコードブロックを書くとその部分は記事のフロントマターとして設定されます。

デプロイの確認

最後に正常にデプロイがされているか確認します。

この記事はIssueを投稿するようにかいているため、あなたがこの記事を正常に閲覧できているならデプロイは正解です。

(画像もしっかりと見えていますか?)

終わりに

GitHubで記事が書けるとなると、今までの心理的ハードルもさがり、筆も走るような気がします。

また、外部サービスを利用しないので料金がかからないのでお財布にも優しいですね。その代わりGitHub APIの仕様変更などがあれば対応しなければなりませんが…。