Netlify CMS (Decap CMS)

現在はDecap CMSとして独立。JAMstack向けのGit-based CMS。静的サイトジェネレータとの連携が強力。

CMSヘッドレスGit-basedJAMstackJavaScriptReactオープンソース
ライセンス
MIT
言語
JavaScript/React
料金
完全無料

CMS

Netlify CMS (Decap CMS)

概要

Netlify CMSは2023年2月にDecap CMSとしてリブランドされ、PM TechHubによってオープンソースプロジェクトとして維持・開発されているGit-basedのヘッドレスCMSです。

詳細

Decap CMS(旧Netlify CMS)は、Gitワークフローのためのオープンソースコンテンツ管理システムで、エディターに優しいUIと直感的なワークフローを提供します。コンテンツはコードと一緒にGitリポジトリに保存されるため、バージョン管理、マルチチャネルパブリッシング、Gitで直接コンテンツ更新が可能です。

本質的には、GitHub、GitLab、BitbucketのAPIを使用してGitワークフローのラッパーとして機能するReactアプリケーションです。JAMstackアーキテクチャに特化しており、Hugo、Jekyll、Gatsby、Next.jsなどのほとんどの静的サイトジェネレータと互換性があります。シンプルな設定で始められるため、小規模プロジェクトから中規模プロジェクトまで幅広く利用されています。

メリット・デメリット

メリット

  • 完全無料: オープンソースでライセンス費用なし
  • Git統合: バージョン管理とワークフローが統一
  • 簡単セットアップ: 2つのファイルを追加するだけで開始可能
  • 静的サイト特化: SSGとの完璧な統合
  • プラットフォーム非依存: どこでもホスティング可能
  • 豊富なSSGサポート: 主要な静的サイトジェネレータをカバー
  • OAuth認証: GitHub/GitLabアカウントでの認証

デメリット

  • 機能が基本的: 高度な機能は限定的
  • 動的機能なし: リアルタイムコンテンツには不適
  • UIの制限: カスタマイズ性が低い
  • 技術的知識が必要: GitとYAMLの基礎知識が必須
  • エンタープライズ機能の欠如: 大規模チーム向け機能が不足
  • メディア管理の制約: 画像管理が基本的

主要リンク

使い方の例

基本的なセットアップ

<!-- /admin/index.html -->
<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Content Manager</title>
</head>
<body>
  <!-- CMSをロード -->
  <script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>

設定ファイル(config.yml)

# /admin/config.yml
backend:
  name: git-gateway # GitHub/GitLab/Bitbucketも利用可能
  branch: main # ブランチ名

# メディアフォルダ設定
media_folder: "static/images/uploads"
public_folder: "/images/uploads"

# コレクション定義
collections:
  - name: "blog" # URLパスで使用
    label: "Blog" # UI表示名
    folder: "content/blog" # ファイル保存先
    create: true # 新規作成を許可
    slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
    fields:
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Featured Image", name: "thumbnail", widget: "image"}
      - {label: "Body", name: "body", widget: "markdown"}

ワークフロー設定

# 編集ワークフローを有効化
publish_mode: editorial_workflow

collections:
  - name: "pages"
    label: "Pages"
    folder: "content/pages"
    create: true
    # ワークフローのステータスを定義
    fields:
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Draft", name: "draft", widget: "boolean", default: true}
      - {label: "Content", name: "body", widget: "markdown"}

Next.jsとの統合

// pages/admin.js
import dynamic from 'next/dynamic'

// クライアントサイドでのみCMSをロード
const AdminWithNoSSR = dynamic(
  () => import('../components/AdminPanel'),
  { ssr: false }
)

export default function Admin() {
  return <AdminWithNoSSR />
}

// components/AdminPanel.js
import { useEffect } from 'react'

export default function AdminPanel() {
  useEffect(() => {
    ;(async () => {
      const CMS = (await import('decap-cms-app')).default
      CMS.init()
    })()
  }, [])

  return <div id="nc-root" />
}

カスタムウィジェット

// カスタムプレビューコンポーネント
CMS.registerPreviewTemplate('blog', BlogPostPreview)

// カスタムウィジェット登録
CMS.registerWidget(
  'color',
  ColorControl,
  ColorPreview
)

// カスタムエディタコンポーネント
CMS.registerEditorComponent({
  id: 'youtube',
  label: 'YouTube',
  fields: [{name: 'url', label: 'YouTube URL', widget: 'string'}],
  pattern: /^youtube (\S+)$/,
  fromBlock: function(match) {
    return {
      url: match[1]
    }
  },
  toBlock: function(obj) {
    return `youtube ${obj.url}`
  },
  toPreview: function(obj) {
    return `<iframe src="${obj.url}" />`
  }
})

ローカル開発バックエンド

# ローカルバックエンドの起動
npx decap-server

# config.ymlでローカルバックエンドを設定
backend:
  name: proxy
  proxy_url: http://localhost:8081/api/v1
  branch: main # ローカルブランチ