ヘッドレスCMS比較:Strapi vs Payload vs Directus 2026年版でコンテンツ管理を構築する
オープンソースラボ編集部 ・ 2026年6月14日
ヘッドレスCMS比較:Strapi vs Payload vs Directus 2026年版でコンテンツ管理を構築する
Next.js・Nuxt・Remixなどのフロントエンドフレームワークと組み合わせてコンテンツ管理を行うヘッドレスCMSが標準的な選択肢となっています。Strapi(Node.js製・最大シェア)・Payload(Next.js統合・TypeScript First)・Directus(SQL直接管理・多機能)の3つが2026年のOSSヘッドレスCMSデファクトスタンダードです。
ヘッドレスCMSを選ぶ理由
- フロントエンド分離: Next.jsやMobileアプリなど複数フロントエンドから同一コンテンツAPIを共有
- 開発者体験: コンテンツタイプを定義するだけで管理UIとREST/GraphQL APIが自動生成
- コスト削減: Contentful($300+/月)→セルフホストで$20/月のVPS費用のみ
- 拡張性: プラグイン・フック・カスタムAPIで完全なビジネスロジックカスタマイズが可能
主要CMSの概要
Strapi
2015年公開、TypeScript製のOSSです。GitHubスター64k+。OSSヘッドレスCMSの最大シェアを持つNode.js製プラットフォームで、Content Type Builder(GUIでスキーマ定義)・REST API・GraphQL・Role & Permissions・Upload Plugin(メディア管理)が標準装備されています。
# Strapi v5 セットアップ
npx create-strapi-app@latest my-cms --dbclient=postgres --dbhost=localhost --dbport=5432 --dbname=strapi --dbusername=strapi --dbpassword=password
cd my-cms
npm run develop
// src/api/article/controllers/article.ts: カスタムコントローラー
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::article.article', ({ strapi }) => ({
// デフォルトのfindをオーバーライドしてカスタムロジックを追加
async find(ctx) {
const { query } = ctx
// 公開記事のみを返す(is_published = true)
query.filters = {
...(query.filters || {}),
is_published: true,
}
const { data, meta } = await super.find(ctx)
// レスポンスを加工
const enriched = data.map(article => ({
...article,
reading_time: Math.ceil(article.attributes.content?.split(' ').length / 200),
}))
return { data: enriched, meta }
},
// SEO用のメタデータを付加するカスタムエンドポイント
async findBySlug(ctx) {
const { slug } = ctx.params
const article = await strapi.entityService.findMany('api::article.article', {
filters: { slug, is_published: true },
populate: ['cover_image', 'author', 'categories', 'seo'],
})
if (!article?.length) return ctx.notFound('記事が見つかりません')
return { data: article[0] }
},
}))
// config/plugins.ts: Strapi プラグイン設定
export default () => ({
upload: {
config: {
provider: 'aws-s3',
providerOptions: {
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
region: process.env.AWS_REGION,
params: { Bucket: process.env.AWS_BUCKET },
},
},
},
email: {
config: {
provider: 'sendgrid',
providerOptions: { apiKey: process.env.SENDGRID_API_KEY },
settings: { defaultFrom: 'noreply@example.com' },
},
},
i18n: { enabled: true },
graphql: { enabled: true, config: { endpoint: '/graphql', playgroundAlways: false } },
})
Payload CMS
2022年公開、TypeScript製のOSSです。GitHubスター33k+。Next.js App RouterにネイティブなTypeScript First CMSで、コレクション・グローバル・ブロックをTypeScriptコードで定義してスキーマの型安全を完全に保証します。データベースにMongoDBまたはPostgreSQLを選択できます。
// payload.config.ts: Payload CMSの完全な設定
import { buildConfig } from 'payload'
import { postgresAdapter } from '@payloadcms/db-postgres'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import { s3Storage } from '@payloadcms/storage-s3'
import { ja } from '@payloadcms/translations/languages/ja'
export default buildConfig({
admin: {
user: 'users',
meta: { titleSuffix: '- My CMS', favicon: '/favicon.ico' },
},
i18n: { supportedLanguages: { ja } },
editor: lexicalEditor(),
db: postgresAdapter({
pool: { connectionString: process.env.DATABASE_URL },
}),
plugins: [
s3Storage({
collections: { media: true },
bucket: process.env.S3_BUCKET,
config: {
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
region: process.env.AWS_REGION,
},
}),
],
collections: [
{
slug: 'articles',
admin: { defaultColumns: ['title', 'status', 'publishedAt'] },
versions: { maxPerDoc: 10, drafts: { autosave: { interval: 100 } } },
hooks: {
beforeChange: [
async ({ data, operation }) => {
// スラッグを自動生成
if (operation === 'create' && !data.slug) {
data.slug = data.title
.toLowerCase()
.replace(/[^a-z0-9-龥]/g, '-')
.replace(/-+/g, '-')
}
return data
},
],
afterChange: [
async ({ doc }) => {
// Next.js ISR キャッシュを再検証
if (doc.status === 'published') {
await fetch(`${process.env.FRONTEND_URL}/api/revalidate?path=/articles/${doc.slug}`)
}
},
],
},
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'slug', type: 'text', unique: true, index: true },
{ name: 'status', type: 'select', options: ['draft', 'review', 'published'], defaultValue: 'draft' },
{ name: 'content', type: 'richText', editor: lexicalEditor() },
{ name: 'coverImage', type: 'upload', relationTo: 'media' },
{ name: 'publishedAt', type: 'date' },
{ name: 'author', type: 'relationship', relationTo: 'users' },
{
name: 'seo', type: 'group', fields: [
{ name: 'title', type: 'text' },
{ name: 'description', type: 'textarea' },
],
},
],
},
],
})
Directus
2004年公開(現在はv10+)、TypeScript製のOSSです。GitHubスター28k+。既存SQLデータベースを直接ラップしてAdminパネルとAPIを即座に生成するデータプラットフォームです。PostgreSQL・MySQL・MariaDB・SQLite・MSSQL・OracleDBに対応し、既存データベースをゼロコードでAPIに変えられます。
# Directus Docker Compose セットアップ
cat > docker-compose.yml << 'EOF'
version: "3.8"
services:
directus:
image: directus/directus:11.0
restart: unless-stopped
ports:
- "8055:8055"
environment:
SECRET: ${DIRECTUS_SECRET}
DB_CLIENT: pg
DB_HOST: postgres
DB_PORT: 5432
DB_DATABASE: directus
DB_USER: directus
DB_PASSWORD: ${DB_PASSWORD}
ADMIN_EMAIL: admin@example.com
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
STORAGE_LOCATIONS: s3
STORAGE_S3_DRIVER: s3
STORAGE_S3_KEY: ${AWS_ACCESS_KEY_ID}
STORAGE_S3_SECRET: ${AWS_SECRET_ACCESS_KEY}
STORAGE_S3_BUCKET: ${S3_BUCKET}
STORAGE_S3_REGION: ${AWS_REGION}
CACHE_ENABLED: "true"
CACHE_STORE: redis
REDIS: redis://redis:6379
depends_on: [postgres, redis]
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: directus
POSTGRES_USER: directus
POSTGRES_PASSWORD: ${DB_PASSWORD}
redis:
image: redis:7-alpine
EOF
docker compose up -d
機能比較表
| 比較項目 | Strapi | Payload | Directus |
|---|---|---|---|
| TypeScript First | △ | ✅ | ✅ |
| Next.js統合 | ✅ | ✅ 最強 | ✅ |
| GraphQL | ✅ | ✅ | ✅ |
| 既存DB接続 | △ | △ | ✅ |
| GUI スキーマ | ✅ | △ | ✅ |
| GitHub Stars | 64k+ | 33k+ | 28k+ |
ヘッドレスCMSはDevOpsカテゴリ/categories/devopsのS3/MinIOで画像・メディアを管理して、CloudflareやNginxでCDN配信するアーキテクチャが本番運用のベストプラクティスです。LLM Toolsカテゴリ/categories/llm-toolsのClaude APIと組み合わせて「記事ドラフト→AIレビュー→SEOメタ自動生成→公開」の完全自動化コンテンツパイプラインを構築できます。
FAQ
Q. Strapi v4とv5の主な変更点は?
A. v5でDocument Service APIへの移行・Draft & Publish v2・TypeScriptの型改善が行われました。主な変更: ①Entity Service APIが廃止→Document Service APIに統一(strapi.documents('api::article.article').findMany())②Draft/Publishがドキュメント単位からコンテンツタイプ単位に変更③プラグインAPIの大幅リファクタリング④Strapi Cloud(SaaS)との統合強化。v4からv5の移行: npx @strapi/upgrade latestコマンドで自動コード変換(一部手動対応が必要)。新規プロジェクトはv5一択です。
Q. Payload CMSをNext.js App Routerと同一プロジェクトに統合するには?
A. create-payload-appでNext.js統合テンプレートを選択すると最もスムーズです。①npx create-payload-app@latest→Website templateを選択②src/app/(payload)/配下にPayloadのAdmin UIが生成③src/payload.config.tsでコレクション定義④Next.jsのServer Componentからpayload.find({ collection: 'articles' })で直接データ取得(APIコール不要)⑤ビルド時にnext build一発でCMS+フロントエンドを同時デプロイ。利点: サーバーサイドレンダリング時にPayload LocalAPIを直接呼び出してネットワークレイテンシ0でコンテンツを取得できます。
Q. Directusで既存のPostgreSQLテーブルを管理UIに接続するには?
A. Directus起動時に既存DBのURLを設定するだけで自動検出されます。手順: ①docker-composeのDB_CLIENT: pgと既存DBの接続情報を設定②起動後にDirectus AdminパネルでCollections→既存テーブルが一覧表示される③フィールドタイプ・バリデーション・リレーションを管理UIから設定④Directus CLIでdirectus schema snapshot→directus schema applyでスキーマをGit管理。注意: Directusはテーブルにid(主キー)があることを要求します。複合主キーのテーブルはdirectus_idバーチャルカラムの設定が必要です。
Q. ヘッドレスCMSのコンテンツをNext.jsでISR配信するには?
A. CMSのWebhookでNext.jsのrevalidatePathを呼び出す設定が標準的です。①Next.js APIルートにPOST /api/revalidateを作成: revalidatePath('/articles/[slug]', 'page')②Strapi/PayloadのafterChangeフックからこのエンドポイントにHTTP POST③認証: REVALIDATION_SECRET環境変数でシークレットトークン照合④Directus: Admin→設定→Webhook→URL・イベント(create/update/delete)・HTTPメソッドPOSTを設定。SWR(stale-while-revalidate): next.config.jsでrevalidate: 60(60秒キャッシュ)を設定するとWebhookなしでも最大1分後に最新コンテンツが表示されます。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| 最大シェア・GUI定義・プラグイン豊富 | Strapi |
| Next.js統合・TypeScript・型安全 | Payload CMS |
| 既存SQL DB・ゼロコードAPI・多DB対応 | Directus |