bon now

ありのままの現実を書き殴る吐き溜め。底辺ITエンジニアの備忘録。
Written by bon who just a foolish IT Engineer.

ブログの投稿にCloudinaryとDecap CMSを導入した

Created Date: 2025/03/07 00:49
Updated Date: 2025/06/01 02:59

はじめに、このブログはMiddlemanでできていて、Vercelにデプロイしている。
そしてソースコードはBitbucketで管理している。

背景

バイクや日常のことを備忘録がてら書こうとすると、わりと画像をアップロードを使うことが多くなってしまうようになった。 MiddlemanをVSCodeで開いてマークダウン記法で書いていた自分にとって、画像をアップロードして加工してpublicフォルダに入れてURLリンクを書いて……という手間がとても煩わしい。

また、ブログをVercelにデプロイしている都合上、合計の静的ファイルサイズを10MB以下にする必要がある。こうなると適当に画像をアップロードするわけにはいかないため、今まで画像を使った記事を書くことはあまりなかったのだが、前述の通り画像を使わざるを得ない場面が増えてきた。
そこで、画像アップロードに対応し、さらに記事作成が楽になるリッチなエディタがあればいいなと思い、調べてみることにした。

AIに相談

最初は「自分で作るか」と思ったのだが、最近では賢いAIが手元にいるわけで、早速自分の困ってることの解決事例がないか相談してみた。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
質問:
静的サイトジェネレーターで記事をWebに公開するのは簡単なのですが、記事を作るのにもう少しリッチなエディタがあると嬉しいんです。
例えば画像を添付したら勝手にS3やCloudflareR2にアップロードしてURLを取得してくれるみたいな。
そういうツールなにかありますか?

----------------------------------------------------------
AIの回答:

静的サイトジェネレーターと連携して使えるリッチなエディタをお探しですね。特に画像アップロード機能があり、S3やCloudflare R2に自動的にアップロードしてくれるようなツールについてご紹介します。

以下のようなツールがあります:

Netlify CMS - 静的サイトジェネレーター(Hugo、Gatsby、Jekyll等)と連携でき、画像アップロードをNetlifyのCDNやお好みのストレージプロバイダーに設定可能です。
Forestry.io (現在はTinaに移行) - GitベースのCMSで、S3などへの画像アップロードをサポートしています。
Tina CMS - Forestryの後継で、Reactベースの直感的なエディタとS3連携機能があります。
Decap CMS (旧Netlify CMS) - オープンソースで継続開発されており、様々なストレージバックエンドをサポート。
Strapi - ヘッドレスCMSとして人気で、S3やCloudflare R2などの画像アップロード先をプラグインで柔軟に設定できます。
Contentful - 大規模プロジェクト向けで、画像管理が充実しています。
Cloudinary + 任意のエディタ - 既存のエディタと組み合わせて使用することも可能です。
これらのツールは静的サイトジェネレーターと連携して、記事執筆とメディア管理をよりスムーズにしてくれます。具体的にどのような静的サイトジェネレーターをお使いか、他に必要な機能があれば、さらに絞り込んだ提案ができます。

期待通り、素晴らしい数の案を出してくれた。

とりあえずブログを運営するうえで、(大変恐縮だが)1円もサービスにお金払わずに済む方法を検討し、今回の「Cloudinary」 + Decap CMS を選択した。
というのもDecap CMSはデフォルトでCloudinaryの画像アップロードと、Middlemanでのローカルサーバーに対応していたからだ。

やり方

公式マニュアルにも書いているとおりに作業する。

Decap CMS Middleman
Decap CMS Cloudinary

  1. 既存のmiddlemanの source ディレクトリに admin ディレクトリを追加し、index.htmlとconfig.ymlを作成
  2. Cloudinaryに登録しAPIキーやオプション設定を admin/config.yml 二追記
  3. 編集時は2つターミナルを開き、片方で bundle exec middleman server 、もう一方で npx decap-server を実行
  4. http://localhost:4567/admin/#/collections/blog にアクセス
  5. これだけである。以下に自分の場合の設定について記述しておく。

    admin/index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Content Manager</title>
        <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
      </head>
      <body>
        <script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
      </body>
    </html>
    

    admin/config.yml

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    backend:
      name: git-gateway
      branch: main # Branch to update (optional; defaults to master)
    
    # ローカル開発用の設定
    local_backend: true
    
    media_folder: "source/images/uploads"
    public_folder: "/images/uploads"
    
    # 画像のアップロード先
    media_library:
      name: cloudinary
      config:
        cloud_name: <Cloudinaryのプロジェクト名>
        api_key: <CloudinaryのAPIキー>
        default_transformations:
          - - fetch_format: auto
              width: 300
              crop: fill
              quality: auto
    
    collections:
      - name: "blog"
        label: "ブログ名"
        folder: "source/post"
        extension: .html.markdown # 既存のファイル拡張子に合わせる
        format: frontmatter
        create: true
        slug: "{{slug}}"
        path: "{{year}}/{{month}}/{{slug}}"  # 既存の記事のディレクトリ形式に合わせる
        fields: # 既存のフィールドに対応させる。config.rbをAIに貼り付けて聞くとよい
          - {label: "タイトル", name: "title", widget: "string"}
          - {
              label: "日付",
              name: "date",
              widget: "datetime",
              format: "YYYY-MM-DD HH:mm",
              date_format: "YYYY-MM-DD",
              time_format: "HH:mm",
              picker_utc: false,
            }
          - {
              label: "カテゴリー",
              name: "category",
              widget: "string",
              required: true,
            }
          - {
              label: "タグ (カンマ区切り)",
              name: "tags",
              widget: "string",
              required: false,
              hint: "複数のタグはカンマで区切ってください (例: 自転車, bicycle, ロードバイク)",
              pattern: ['^[^,]+(,[^,]+)*$', "カンマ区切りで入力してください"]
            }
          - {
              label: "アイキャッチ画像",
              name: "eyecatch",
              widget: "image",
              required: false,
            }
          - {label: "本文", name: "body", widget: "markdown"}
          - {label: "公開", name: "published", widget: "boolean", default: true}
    

    これでとても記事の編集が楽になった。今後は画像を使った記事も作っていきたいと思う。手始めにバイクや自転車関連の記事を画像付きで書いていこうと思う。

local_offer
folder blog