はじめに
静的サイトジェネレーターでブログやコーポレートサイトを作ったとき、こんな壁にぶつかったことはないでしょうか。
「記事はMarkdownでGit管理したい。でも記事を書くたびにPull Requestを出すのは面倒だし、非エンジニアには頼めない」
かといってWordPressのようなCMSを別に導入すると、データベースやサーバーの管理が必要になり、せっかくの静的サイトの身軽さが失われてしまいます。この悩みに応えていたのがNetlify CMSでしたが、2022年ごろから開発が停滞し、「もう使い続けて大丈夫なのか」と不安に思った人も多いはずです。そのNetlify CMSをコミュニティがフォークし、開発を引き継いだのが今回紹介するDecap CMSです。
とはいえ、読むより触った方が早いと思います。ブラウザだけで動くDecap CMSの管理画面をこの記事内で実際に動かせるので、先に挙動を見たい方はこちらからどうぞ。
Decap CMSとは
Decap CMSは、静的サイトジェネレーター向けのGitベースCMSです。もとはNetlify社が開発していた「Netlify CMS」ですが、Netlifyが積極的な開発から距離を置くようになったあと、コミュニティがdecaporg名義でフォークし、2023年に「Decap CMS」として引き継ぎました。GitHub上では19,000以上のスターを獲得しており、直近の更新も継続的に行われています。
React製のシングルページアプリケーションとして動作し、YAML(またはJSON)の設定ファイルでコンテンツモデルを定義するだけで、記事投稿・編集用の管理画面が手に入ります。コンテンツはデータベースではなくGitリポジトリ内のMarkdownやJSONファイルとして保存されるため、既存のGitワークフロー(レビュー・履歴管理)をそのまま活かせます。
主な特徴
- バックエンドを選べる - GitHub、GitLab、Bitbucket、Azure DevOpsなど複数のGitホスティングに対応しており、特定のサービスにロックインされません。Netlifyでホストしていなくても
git-gatewayを使わずに直接GitHubなどへ接続できます - エディトリアルワークフロー -
publish_mode: editorial_workflowを設定するだけで、下書き・レビュー中・公開準備完了という3段階のワークフローボードが管理画面に追加されます - 豊富なウィジェット - 文字列、Markdown、画像、日時、リスト、オブジェクト、他コレクションへの参照(Relation)など、コンテンツの型に応じたウィジェットが標準で揃っています
- サーバー不要 - CDNからスクリプトを1本読み込むだけで動作するため、管理画面用の専用サーバーやデータベースを別途用意する必要がありません
- OSSとして無料で使える - MITライセンスで公開されており、SaaS的な課金や機能制限がありません
インストール
Decap CMSの導入方法は大きく2つあります。
CDNで手早く試す(クイックスタート)
サイトの/adminディレクトリにindex.htmlとconfig.ymlを置くだけで始められます。
<!-- admin/index.html -->
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Content Manager</title>
</head>
<body>
<script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>
# admin/config.yml
backend:
name: github
repo: your-name/your-repo
branch: main
media_folder: "static/images"
collections:
- name: "posts"
label: "Posts"
folder: "content/posts"
create: true
fields:
- { label: "Title", name: "title", widget: "string" }
- { label: "Body", name: "body", widget: "markdown" }
npmパッケージとして導入する
React製のビルドパイプラインに組み込みたい場合は、npmでインストールできます。
npm install decap-cms-app
yarn add decap-cms-app
Decap CMSのサンプルを動かす
下のサンプルは、Decap CMSの本体(decap-cmsパッケージ)をCDNから読み込み、CMS.init()でGitリポジトリなしのtest-repoバックエンドを使って初期化したものです。test-repoはDecap CMS公式のデモサイト(demo.decapcms.org)でも使われている、ブラウザ内メモリだけで完結するバックエンドで、実際の記事作成・公開の操作感をそのまま試せます(ページを再読み込みすると内容は消えます)。
管理画面の要点は、CMS.init()に渡す設定オブジェクトだけです。backendでデータの保存先、collectionsで編集できるコンテンツの型(フィールド構成)を定義します。
CMS.init({
config: {
backend: { name: 'test-repo' },
media_folder: 'images',
collections: [
{
name: 'posts',
label: 'Blog Posts',
folder: 'posts',
create: true,
fields: [
{ name: 'title', label: 'Title', widget: 'string' },
{ name: 'thumbnail', label: 'Thumbnail', widget: 'image', required: false },
{ name: 'body', label: 'Body', widget: 'markdown' },
],
},
],
},
})
実際に動かせるサンプルが以下です。「New Blog Posts」から新規記事を作成し、タイトルや本文を入力してみてください。右側にプレビューがリアルタイムで表示されます。
fieldsの配列を書き換えると、そのまま管理画面のフォームに反映されます。たとえばwidget: 'string'をwidget: 'text'に変えると複数行のテキストエリアになりますし、required: falseを外せばそのフィールドは必須項目になります。Decap CMSの管理画面は、あくまでこの設定オブジェクトの見た目にすぎないことが体感できるはずです。
基本的な使い方
Decap CMSの設定ファイルは、大きく分けて3つの要素で構成されます。
- backend - コンテンツの保存先(GitHub、GitLabなど)と認証方式
- media_folder - 画像などのメディアファイルを保存するディレクトリ
- collections - 編集可能なコンテンツの型。
folder(複数ファイルの集合。ブログ記事など)とfiles(単一ファイル。トップページ設定など)の2種類があります
backend:
name: github
repo: your-name/your-repo
branch: main
media_folder: "static/images"
public_folder: "/images"
collections:
- name: "posts"
label: "ブログ記事"
folder: "content/posts"
create: true
slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
fields:
- { label: "タイトル", name: "title", widget: "string" }
- { label: "公開日", name: "date", widget: "datetime" }
- { label: "本文", name: "body", widget: "markdown" }
folderコレクションにcreate: trueを指定すると、管理画面に「New Post」ボタンが表示され、slugテンプレートに沿ったファイル名で新規記事が作られます。フィールドの型はwidgetで指定し、string(1行テキスト)、text(複数行)、markdown(Markdownエディタ)、image(画像アップロード)などを組み合わせてコンテンツモデルを設計します。
実践的なユースケース
リストウィジェットとオブジェクトで構造化データを組む
FAQページや料金表のように「同じ形式の項目が繰り返される」コンテンツは、widget: 'list'の中に複数フィールドをネストすることで表現できます。単一ファイルを編集するfilesコレクションと組み合わせると、ページ単位の構造化データ編集にも使えます。
{
name: 'items',
label: '質問リスト',
widget: 'list',
fields: [
{ name: 'question', label: 'Question', widget: 'string' },
{ name: 'answer', label: 'Answer', widget: 'text' },
],
}
以下のサンプルでは、FAQページ用のfilesコレクションを定義しています。「質問リスト」の「Add」ボタンを押すたびに、Question/Answerのペアが1件追加されます。
エディトリアルワークフローで下書きから公開までを管理する
複数人でレビューしながら記事を公開したい場合は、publish_mode: 'editorial_workflow'を設定に追加します。すると管理画面の左側に「ワークフロー」というメニューが増え、記事が「Draft(下書き)」「In Review(レビュー中)」「Ready(公開準備完了)」の3レーンで管理できるようになります。
{
backend: { name: 'test-repo' },
publish_mode: 'editorial_workflow', // これを追加するだけ
collections: [ /* ... */ ],
}
実際に動かして、記事を1件保存したあと画面左の「Workflow」メニューを開いてみてください。保存した記事がDraftレーンに現れ、ステータスを進めるたびにレーンを移動します。
GitHub/GitLab/Bitbucketに接続して本番運用する
ここまでのtest-repoはブラウザ内で完結する検証用バックエンドでしたが、実運用では実際のGitホスティングサービスに接続します。backend.nameをgithub・gitlab・bitbucketのいずれかに変え、対象リポジトリを指定するだけです(OAuthの認証エンドポイントが別途必要になるため、この設定単体をブラウザ内で動かすことはできません)。
backend:
name: github
repo: your-name/your-repo
branch: main
# Netlifyでホストしていない場合、base_urlに自前のOAuthプロバイダーを指定する
# base_url: https://your-oauth-provider.example.com
# auth_endpoint: auth
Netlifyでホストしている場合はgit-gatewayバックエンドを使うと、Netlify Identityの認証情報でGitHub/GitLab/Bitbucketへの書き込みを代行してくれるため、OAuthアプリの個別登録が不要になります。それ以外のホスティングでは、Decap CMS公式が案内しているOAuthプロバイダーの実装例を参考に、認証用のサーバーレス関数などを別途用意します。
まとめ
Decap CMSは、Netlify CMSという「Gitベースの管理画面」という発想を、コミュニティの手で存続させたプロジェクトです。特定のGitホスティングにロックインされず、Editorial Workflowのような実務で欲しくなる機能も標準搭載しており、静的サイトに「非エンジニアでも触れる管理画面」を後付けしたいときの有力な選択肢になります。
まずは今回のサンプルのようにtest-repoバックエンドで挙動を確かめ、コンテンツモデルの設計に慣れてから、実際のGitリポジトリに接続してみるとスムーズです。