はじめに
「管理画面、自分で作るのめんどくさいな」
Webアプリを開発していると、必ずぶつかる壁があります。フロントエンドはReactやNext.jsでサクサク作れるのに、管理画面やバックエンドになると急に手が止まる。認証、権限管理、CRUD操作、リッチテキストエディタ...地味だけど、作り込むと時間が溶けていく。
WordPressは重いし、Strapi は設定が多い。microCMSは便利だけど、カスタマイズに限界がある。そんな「ちょうどいいCMS」を探していたときに見つけたのがPayloadです。
GitHubスターは39,000を超えていて、2025年にはFigmaに買収されたことでも話題になりました。「Next.jsネイティブ」を掲げていて、既存のNext.jsプロジェクトにそのまま組み込めるというのが大きな特徴。
正直なところ、これは使ってみる価値があると思います。
Payloadとは
Payloadは「The Next.js Headless CMS and App Framework」を掲げる、オープンソースのヘッドレスCMSです。
他のCMSと決定的に違うのは、Next.jsの/appフォルダに直接インストールできること。つまり、フロントエンドとバックエンドが同じプロジェクト内で完結します。React Server Componentsからデータベースを直接クエリできるので、API層を挟む必要がない。
TypeScriptベースで、コレクション(データ構造)をコードで定義するアプローチを取っています。GUIでポチポチ設定するタイプのCMSとは違って、Gitで管理できるし、型安全にデータを扱える。エンジニアにとっては、こっちの方がしっくりくるんですよね。
特徴・メリット
Next.jsネイティブ
これ、意外と革命的なんですよ。従来のヘッドレスCMSは、フロントエンドとバックエンドが別々のサービスになっていて、APIで繋ぐ形が一般的でした。Payloadは違います。
your-nextjs-app/
├── app/
│ ├── (frontend)/ # フロントエンド
│ └── (payload)/ # 管理画面(自動生成)
├── collections/ # データ定義
└── payload.config.ts # 設定ファイル
1つのNext.jsプロジェクトの中に、フロントエンドも管理画面もバックエンドも全部入っている。デプロイも1つ。これがどれだけ楽か、複数サービスを運用したことがある人なら分かると思います。
コードファーストなアプローチ
コンテンツの構造は、TypeScriptで定義します。
import { CollectionConfig } from 'payload'
export const Posts: CollectionConfig = {
slug: 'posts',
admin: {
useAsTitle: 'title',
},
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'content',
type: 'richText',
},
{
name: 'publishedDate',
type: 'date',
},
{
name: 'author',
type: 'relationship',
relationTo: 'users',
},
],
}
これだけで、管理画面に「Posts」というメニューが追加されて、記事の作成・編集・削除ができるようになります。マイグレーションもコードベースで管理できる。
充実した標準機能
ヘッドレスCMSを選ぶとき、結局「どこまで自分で作らなきゃいけないか」が重要になります。Payloadは以下が全部入り:
- 認証・ユーザー管理: ビルトイン
- アクセス制御: フィールドレベルまで設定可能
- バージョン管理・ドラフト: ワンクリックで有効化
- 多言語対応(i18n): フィールドごとのローカライゼーション
- リッチテキストエディタ: Lexical(Meta製)を採用
- メディア管理: 画像リサイズも自動
- REST/GraphQL API: 自動生成
個人的には、アクセス制御がフィールドレベルまで細かく設定できるのがポイント高いですね。「この項目は管理者だけ編集可能」みたいな要件、実務では頻繁にあるので。
Vercel/Cloudflareにワンクリックデプロイ
サーバーレス環境との相性が良くて、Vercel や Cloudflare Workers にワンクリックでデプロイできます。
Cloudflare なら Workers + R2(ストレージ)+ D1(データベース)のスタックで完結。Vercel なら Neon + Vercel Blob の組み合わせが推奨されています。
個人プロジェクトなら、これで月額ほぼゼロで運用できるのは嬉しい。
Figmaによる買収
2025年にFigmaに買収されました。これ、結構重要な話で、オープンソースプロジェクトとしての継続性に不安を感じる人もいるかもしれません。ただ、公式発表では「オープンソースのまま継続」と明言されています。
むしろ、Figmaのデザインツールとの連携強化が期待できるので、デザイナーとエンジニアのワークフローがさらにスムーズになる可能性はありますね。
インストール方法
インストールは驚くほど簡単です。
新規プロジェクトの場合
pnpx create-payload-app@latest
対話形式でプロジェクト名やデータベースを選択すると、すぐに使える状態でプロジェクトが生成されます。
テンプレートを指定する場合は:
pnpx create-payload-app@latest -t website
「website」テンプレートには、ブログやランディングページに必要なコレクションが最初から含まれています。
既存のNext.jsプロジェクトに追加
既存のプロジェクトに追加する場合は:
pnpm add payload @payloadcms/next @payloadcms/db-postgres
データベースアダプターは用途に応じて選択:
@payloadcms/db-postgres: PostgreSQL@payloadcms/db-mongodb: MongoDB
設定ファイルを作成:
// payload.config.ts
import { buildConfig } from 'payload'
import { postgresAdapter } from '@payloadcms/db-postgres'
export default buildConfig({
secret: process.env.PAYLOAD_SECRET || '',
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URL || '',
},
}),
collections: [
// ここにコレクションを追加
],
})
基本的な使い方
1. コレクションの定義
まず、データ構造を定義します。ブログ記事なら:
// collections/Posts.ts
import { CollectionConfig } from 'payload'
export const Posts: CollectionConfig = {
slug: 'posts',
admin: {
useAsTitle: 'title',
defaultColumns: ['title', 'status', 'publishedDate'],
},
access: {
read: () => true, // 誰でも読める
create: ({ req }) => !!req.user, // ログインユーザーのみ
},
fields: [
{
name: 'title',
type: 'text',
required: true,
},
{
name: 'slug',
type: 'text',
unique: true,
admin: {
position: 'sidebar',
},
},
{
name: 'content',
type: 'richText',
},
{
name: 'status',
type: 'select',
options: ['draft', 'published'],
defaultValue: 'draft',
},
{
name: 'publishedDate',
type: 'date',
},
],
}
2. 設定ファイルに登録
// payload.config.ts
import { Posts } from './collections/Posts'
export default buildConfig({
// ...
collections: [Posts],
})
3. 開発サーバーを起動
pnpm dev
http://localhost:3000/admin にアクセスすると、管理画面が表示されます。最初のアクセス時にユーザー登録を求められるので、管理者アカウントを作成してください。
4. フロントエンドからデータを取得
React Server Components なら、直接データベースをクエリできます:
// app/blog/page.tsx
import { getPayloadClient } from '@/lib/payload'
export default async function BlogPage() {
const payload = await getPayloadClient()
const posts = await payload.find({
collection: 'posts',
where: {
status: { equals: 'published' },
},
sort: '-publishedDate',
})
return (
<ul>
{posts.docs.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
REST APIを使う場合は /api/posts にリクエストすればOK。GraphQL も /api/graphql で利用可能です。
実践的なユースケース
企業サイト + ブログ
よくあるパターン。固定ページとブログ記事を管理したい場合:
Pagesコレクション:会社概要、サービス紹介などの固定ページPostsコレクション:ブログ記事Mediaコレクション:画像管理
Payloadのブロックフィールドを使えば、ランディングページのセクションをドラッグ&ドロップで並び替えられる管理画面も作れます。
ECサイトのバックエンド
商品管理、カテゴリ管理、注文管理。アクセス制御を細かく設定すれば、スタッフごとに操作できる範囲を制限できます。
Stripeとの連携もプラグインで対応しているので、決済周りも比較的楽に実装できます。
マルチテナントSaaS
テナントごとにデータを分離したい場合、Payloadの「マルチテナント」機能が使えます。1つのコードベースで複数の顧客を管理できるので、運用コストを抑えられる。
ドキュメントサイト
バージョン管理と多言語対応がビルトインなので、技術ドキュメントの管理にも向いています。Markdownも扱えますし、Lexicalエディタは拡張性が高いので、独自の埋め込みコンポーネントも追加可能。
注意点
正直なところ、いくつか気をつけるべき点もあります。
学習コストはそれなりにある
コードファーストのアプローチなので、設定ファイルを書く必要があります。GUIでポチポチやりたい人には向かないかもしれません。ただ、TypeScriptに慣れているエンジニアなら、むしろ直感的に感じるはず。
日本語の情報が少ない
海外では人気がありますが、日本語のチュートリアルや記事はまだ少ないです。公式ドキュメントは英語ですが、分かりやすく書かれているので、そこまで困らないとは思います。
v3での破壊的変更
Payload 3.0でNext.jsネイティブになり、アーキテクチャが大きく変わりました。v2からの移行ガイドはありますが、既存プロジェクトのアップグレードには時間がかかる可能性があります。新規プロジェクトなら気にしなくてOK。
まとめ
Payloadは「Next.jsでアプリを作っているけど、管理画面やバックエンドを楽に作りたい」という、まさに現代のWeb開発者のニーズに刺さるツールです。
- Next.jsプロジェクトに直接インストール可能
- TypeScriptで型安全にデータ構造を定義
- 認証、権限管理、バージョン管理がビルトイン
- REST/GraphQL APIが自動生成
- Vercel/Cloudflareにワンクリックデプロイ
- MITライセンスで完全無料
30代になって思うのは、「作らなくていいものは作らない」ということ。管理画面を1から作り込む時間があったら、ビジネスロジックに集中した方がいい。PayloadはそのためのツールをすべてMITライセンスで提供してくれます。
まずは pnpx create-payload-app@latest -t website で触ってみてください。5分で動きますし、管理画面の出来栄えに驚くと思います。
公式サイト: https://payloadcms.com GitHub: https://github.com/payloadcms/payload ドキュメント: https://payloadcms.com/docs
