Payload CMS入門:PostsコレクションでCRUDと下書きプレビューを試す

中級 | 12分 で読める | 2026.04.24

公式ドキュメント

Payloadは、TypeScriptでデータ構造を定義すると、管理画面とAPIを生成するCMSです。今回はpostsコレクションを一つだけ作り、管理画面とREST APIの対応を確認します。

Posts Collectionを1つ定義すると管理画面とREST APIが提供され、下書き・公開を含む同じ記事データを扱う関係図

今回やること

  • 公式の空テンプレートから起動する
  • titleslugbodyを持つPostsを登録する
  • 管理画面でCRUDを試す
  • draftを保存し、PreviewからJSONを確認する

Collectionは同じ構造を持つ文書のまとまりです。postsを定義すると、Payloadは管理画面の一覧・編集フォームと、/api/posts以下のREST APIを生成します。今回は独自APIや複数Collectionを追加しません。

プロジェクトを作る

Payloadの要件に合うNode.jsと、Dockerまたは選択するDBを準備します。

npx create-payload-app@latest -t blank

質問に従ってプロジェクト名とDBを選び、作成したディレクトリへ移動します。以降は生成されたREADME.mdにあるコマンドを優先してください。一般的には次で起動できます。

pnpm dev

ブラウザでhttp://localhost:3000/adminを開き、最初の管理者を作ります。

Postsコレクションを作る

src/collections/Posts.tsを作ります。

import type { CollectionConfig } from "payload";

export const Posts: CollectionConfig = {
  slug: "posts",
  admin: {
    useAsTitle: "title",
    preview: ({ id }) => `/api/posts/${id}?draft=true`,
  },
  access: {
    read: ({ req }) =>
      req.user ? true : { _status: { equals: "published" } },
    create: ({ req }) => Boolean(req.user),
    update: ({ req }) => Boolean(req.user),
    delete: ({ req }) => Boolean(req.user),
  },
  versions: {
    drafts: true,
  },
  fields: [
    { name: "title", type: "text", required: true },
    { name: "slug", type: "text", required: true, unique: true },
    { name: "body", type: "textarea", required: true },
  ],
};

payload.config.tsPostsを読み込み、既存のcollectionsへ追加します。

import { Posts } from "./collections/Posts";

export default buildConfig({
  // 生成済みのdb、editor、secretなどはそのまま残す
  collections: [Users, Posts],
});

テンプレートによって既存Collection名やimport位置は異なります。buildConfig全体を上の短い例で置き換えず、Postsのimportと配列要素だけを加えてください。

設定の役割は次のとおりです。

設定役割
slug: "posts"管理画面とAPIで使う名前
versions.drafts公開版とは別に下書きを保存
access未ログイン時は公開済みの読み取りだけ許可
admin.preview管理画面のPreviewボタンの移動先

CRUDを確認する

開発サーバーを再起動し、管理画面のPostsから次を試します。

  1. title: 最初の記事slug: first-post、本文を入力して作成する
  2. 一覧で作った記事を参照する
  3. タイトルを更新して保存する
  4. 最後に記事を削除する

削除前に、REST APIでも一覧を確認できます。

curl http://localhost:3000/api/posts

Collectionのslugがpostsなので、Payloadが/api/postsを生成します。この設定では、ログインしていない人は公開済み文書だけを読め、作成・更新・削除とdraft取得はログインした管理者に限られます。

REST APIでは、一覧はGET /api/posts、1件はGET /api/posts/<ID>、更新はPATCH /api/posts/<ID>、削除はDELETE /api/posts/<ID>です。今回は認証情報をcurlへコピーせず、書き込み操作を管理画面で行います。

一覧応答は文書配列そのものではなく、docsとページ情報を含むオブジェクトです。フロントエンドから使う時はresult.docsを読み、件数が増えたらpagelimitも扱います。

下書きをプレビューする

記事をもう一つ作り、Save Draftで下書き保存します。保存後に管理画面のPreviewを押すと、/api/posts/<ID>?draft=trueが開き、ログイン中の管理者として下書きJSONを確認できます。

このプレビューは表示ページではなく、draft取得の最小確認です。実際のサイトでは、推測できないpreview secretの検証、管理者認証、Next.jsのdraft modeを備えた専用ルートを作ります。

Previewを押す前に一度Save Draftを行います。まだ保存されていない新規文書には確定したIDがないため、プレビューURLも確定しません。

成功確認

  • 管理画面のPostsに作成した文書が表示される
  • GET /api/postsで公開した文書が返る
  • 下書きのPreviewで_status: "draft"の文書を確認できる
  • 更新内容が保存され、削除後は一覧から消える

よくあるつまずき

Postsが管理画面に出ない

Postsをexportしただけでは登録されません。payload.config.tscollections配列へ追加し、開発サーバーを再起動します。

Previewで公開版しか見えない

versions.drafts、URLのdraft=true、管理者としてログインしているかを確認します。公開APIへ認証なしでdraftを返してはいけません。

練習

publishedAtというdateフィールドを一つ追加してください。管理画面で値を保存し、REST APIのJSONにも同じ値が含まれることを確認します。

後片付け

練習用文書は管理画面から削除します。開発サーバーはCtrl + Cで停止します。DBコンテナをテンプレートが起動した場合は、生成されたREADMEの停止手順を使います。

次のステップ

参考リソース

← 一覧に戻る
PR
PR
PR
PR