メインコンテンツまでスキップ

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/postsPOST /api/postsGET /api/posts/:id
  • GraphQL: Posts クエリと createPost 等のミューテーション
  • DB: Postgres に posts テーブル (id, title, createdAt, updatedAt)

が同時に立ち上がります。

Config の主要トップレベルプロパティ

公式 doc に列挙されている主なプロパティを役割でグルーピングするとこうなります:

グループプロパティ役割
必須secret / dbJWT 署名鍵 / DB アダプタ
データモデルcollections / globals繰り返しドキュメントとシングルトン
Admin UIadmin / editor管理画面の挙動 / リッチエディタ (Lexical)
APIroutes / endpoints / graphQL / cors / csrfURL 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 機能の有効化
hooksbeforeChange / afterChange など、ライフサイクル中の処理を挟む
access関数で書くアクセス制御 (詳細は 04 Security & Lifecycle)
admin一覧表示するカラム / 並び順 / グループ分類など UI のカスタマイズ
labels「Post」「Posts」のような単複ラベル (Admin UI 表示用)
timestampscreatedAt / 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、と覚えると迷いません。

主要プロパティ

slugfields は必須、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' → input
  • type: 'textarea' → textarea
  • type: 'richText' → Lexical エディタ
  • type: 'relationship' → セレクタ (関連 Collection をフィルタしながら選ぶ)
  • type: 'array' → 子要素を追加できる繰り返し UI
  • type: '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 操作の裏側で同じ仕組みが走っています。

出典: Collections (公式 doc)

この章のまとめ

  • PayloadCMS は Config-First / code-first CMS で、payload.config.ts 1 本からスキーマ・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 のデータモデリング層を一気に俯瞰します。

参考