Core Concepts — Config-First / Collections / Globals
この章のゴール
- PayloadCMS の Config-First 思想 が何を意味するか言語化できる
payload.config.tsの役割と、書き換えると何が変わるかの全体像が掴める- Collections (繰り返しドキュメント) と Globals (シングルトン) の使い分けの基準を持てる
- 最小 config から「動く CMS」が立ち上がる仕組みを直感的に理解する
Config-First とは何か
公式 doc は PayloadCMS を「config-based, code-first CMS and application framework」と表現しています (Configuration Overview)。管理画面のクリック操作で設定を組み立てるのでなく、TypeScript の Config ファイル 1 本にデータモデル・認証・アクセス制御・Admin UI の見た目までを宣言し、そこからすべてが組み上がる、という設計哲学です。
具体的には次が config から自動生成されます:
- 管理画面 (Admin UI) — Collections / Globals / Fields から React コンポーネントが生成される
- REST / GraphQL API — Collection ごとにエンドポイントとスキーマが自動生成される
- TypeScript 型 —
payload-types.tsとして書き出し、フロントから import できる - DB スキーマ / migration — Postgres adapter なら Drizzle ORM ベースで migration ファイルが生成される
逆に言うと、config を書き換えれば DB スキーマも Admin UI も API もまとめて変わるということです。Git に config を入れるだけで、CMS のスキーマ変更が PR でレビュー可能になる — これが Config-First の実利です。
payload.config.ts の歩き方
配置場所
公式 doc によれば payload.config.ts は プロジェクトのルートに置くのが標準で、環境変数 PAYLOAD_CONFIG_PATH で別の場所を指定することもできます。Next.js 同居構成 (06 章で詳述) でも基本はルートです。
最小 config 例
公式 doc の最小例を Postgres に合わせて書くとこうなります:
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: [
{
slug: 'posts',
fields: [
{ name: 'title', type: 'text' },
],
},
],
})
これだけで:
- Admin UI:
/admin配下にpostsの CRUD 画面が立ち上がる (デフォルトでは/admin/collections/postsパターン) - REST:
GET /api/posts、POST /api/posts、GET /api/posts/:id等 - GraphQL:
PostsクエリとcreatePost等のミューテーション - DB: Postgres に
postsテーブル (id, title, createdAt, updatedAt)
が同時に立ち上がります。
Config の主要トップレベルプロパティ
公式 doc に列挙されている主なプロパティを役割でグルーピングするとこうなります:
| グループ | プロパティ | 役割 |
|---|---|---|
| 必須 | secret / db | JWT 署名鍵 / DB アダプタ |
| データモデル | collections / globals | 繰り返しドキュメントとシングルトン |
| Admin UI | admin / editor | 管理画面の挙動 / リッチエディタ (Lexical) |
| API | routes / endpoints / graphQL / cors / csrf | URL prefix / 独自 API / GraphQL 設定 / セキュリティ |
| 拡張 | plugins / hooks / onInit | プラグイン / Config 全体に効くフック / 初期化処理 |
| 国際化 | localization / i18n | フィールドの多言語化 / Admin UI 言語 |
| その他 | serverURL / email / upload / typescript / logger / telemetry | 公開 URL / メール / アップロード / 型出力 / ログ / テレメトリ |
完全な一覧は Configuration Overview を参照してください。
型のインポート
Config そのものの型は payload から型として import できます:
import type { Config, SanitizedConfig } from 'payload'
Config は手書きする側の生 config、SanitizedConfig は PayloadCMS が内部で正規化したあとの形です。
Collections (繰り返しドキュメント)
Collection とは
Collection は 同じスキーマを共有する「繰り返しのドキュメント」をまとめる単位です。一般的なブログでいえば posts / users / media / categories のような単位がそれぞれ Collection になります。
公式 doc によれば、各 Collection は次を 自動で持ちます:
- Local / REST / GraphQL の 3 種類の API
- Admin UI の一覧・編集画面
- 同名の DB テーブル / コレクション (Postgres or Mongo)
- Access Control・Hooks・Versions などの設定可能なオプション
主要プロパティ
| プロパティ | 役割 |
|---|---|
slug (必須) | URL とテーブル名のもとになる識別子 |
fields (必須) | フィールド定義の配列 (詳細は 03 Data Modeling) |
auth | この Collection を認証エンドポイント (ログイン可能なユーザー) にする |
upload | アップロード対応 (画像・PDF など Media collection 化) |
versions | ドキュメントのバージョン管理 / Draft 機能の有効化 |
hooks | beforeChange / afterChange など、ライフサイクル中の処理を挟む |
access | 関数で書くアクセス制御 (詳細は 04 Security & Lifecycle) |
admin | 一覧表示するカラム / 並び順 / グループ分類など UI のカスタマイズ |
labels | 「Post」「Posts」のような単複ラベル (Admin UI 表示用) |
timestamps | createdAt / updatedAt の自動付与 (デフォルト ON) |
最小 Collection 定義
公式 doc が示す最小例:
import type { CollectionConfig } from 'payload'
export const Posts: CollectionConfig = {
slug: 'posts',
fields: [
{
name: 'title',
type: 'text',
},
],
}
これだけで posts の管理画面、API、テーブルが揃います。実プロジェクトでは auth: true (Users) や upload: { staticDir: '...' } (Media)、versions: { drafts: true } (Draft 可能) を組み合わせていきます。
Globals (シングルトン)
Global とは
Global は「この CMS にひとつだけ存在するドキュメント」を扱う単位です。Collection が「繰り返し」なのに対して、Global は「シングルトン」です。
公式 doc の典型例:
- Header Navigation — サイトのヘッダーメニュー
- Site-wide Banner Alerts — 全ページに出すお知らせバナー
- App-wide Localized Strings — UI 文言の翻訳辞書
「複数あるはずがない / あっても 1 つで足りる」ものは Global、それ以外は Collection、と覚えると迷いません。
主要プロパティ
slug と fields は必須、access / hooks / versions / admin / lockDocuments などのオプションが Collection とほぼ同じ感覚で並びます。
最小 Global 定義
import type { GlobalConfig } from 'payload'
export const Header: GlobalConfig = {
slug: 'header',
fields: [
{
name: 'nav',
type: 'array',
fields: [
{ name: 'label', type: 'text' },
{ name: 'page', type: 'relationship', relationTo: 'posts' },
],
},
],
}
Admin UI にはシングルページが現れ (デフォルトでは /admin/globals/header 配下)、API も GET /api/globals/header のようにシングルトン用エンドポイントが用意されます (公式 REST API doc 確認済)。
Collection と Global の使い分け早見表
| こういうもの | Collection / Global |
|---|---|
| ブログ記事 / 商品 / ユーザー / 画像 | Collection |
| サイトのヘッダー / フッターメニュー | Global |
| 利用規約・プライバシーポリシーの本文 | Global (バージョン管理を入れる) |
| カテゴリー (記事に紐付ける分類) | Collection |
| サイト設定 (SEO 用 OGP デフォルト等) | Global |
| お知らせ (一覧表示する更新情報) | Collection |
| トップページのヒーローセクション | Global (固定ページがあるなら Collection でも可) |
迷ったら 「これは 2 つ以上になり得るか?」 を自問するのが最も簡単な判別軸です。
Admin UI は config から組み上がる
ここまで見た config からは、Admin UI が 明示的にコンポーネントを書かなくても組み上がります。一覧画面・編集フォーム・バリデーション・関連リソース選択 (Relationship) などはすべて Field の type から導出されます。
type: 'text'→ inputtype: 'textarea'→ textareatype: 'richText'→ Lexical エディタtype: 'relationship'→ セレクタ (関連 Collection をフィルタしながら選ぶ)type: 'array'→ 子要素を追加できる繰り返し UItype: 'blocks'→ ブロック型コンテンツ (Hero / RichText など複数の Block を順番に並べる)
これらの詳細は 03 Data Modeling で扱います。Admin UI のさらなるカスタマイズ (ロゴ・ナビ・独自 React コンポーネント差し込み) は 07 Admin / Media / Deploy で扱います。
実装例 — Collection に並び順を持たせる (Fractional Indexing)
Admin UI でドキュメントを drag-and-drop で並び替えたい、というのは Collection 設計の典型ニーズです。PayloadCMS は Fractional Indexing を Collection 標準機能として持っています (Collections doc)。
Collection 定義側で orderable: true を指定:
import type { CollectionConfig } from 'payload'
export const Categories: CollectionConfig = {
slug: 'categories',
orderable: true,
fields: [
{ name: 'name', type: 'text', required: true },
],
}
プログラム的に並び順を制御したいときは、公式が payload/shared から提供するユーティリティを使います:
import { generateKeyBetween, generateNKeysBetween } from 'payload/shared'
// 既存キー 'a0' と 'a1' の間に挿入するキー
const newKey = generateKeyBetween('a0', 'a1')
// 先頭に挿入
const startKey = generateKeyBetween(null, 'a0')
// 末尾に追加
const endKey = generateKeyBetween('a1', null)
// 'a0' と 'a1' の間に 5 個のキーをまとめて生成
const keys = generateNKeysBetween('a0', 'a1', 5)
整数の連番でなく キー間のキーを生成することで、並び替え時に既存の全ドキュメントを更新する必要がない、という設計です。Admin UI 側の drag-and-drop 操作の裏側で同じ仕組みが走っています。
この章のまとめ
- PayloadCMS は Config-First / code-first CMS で、
payload.config.ts1 本からスキーマ・Admin UI・API・型が同時に立ち上がる - 主要プロパティは 必須 (secret / db) + データモデル (collections / globals) が骨格、あとは
admin/editor/pluginsなどが肉付け - Collection = 繰り返し (posts / users / media)、Global = シングルトン (header / settings)
- Field の
typeを書けば Admin UI が自動生成され、明示的な React コードは原則不要 - 並び順は
orderable: true+payload/sharedの Fractional Indexing で制御
次に読む
次章 03 Data Modeling — Fields / Lexical / Relationships / Versions / Localization では、Collection を構成する Field の世界を扱います。プリミティブな text / number から、Blocks / Lexical Rich Text / Localization / Versions まで、PayloadCMS のデータモデリング層を一気に俯瞰します。