Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

payload

Payload CMSプロジェクト(payload.config.ts、コレクション、フィールド、フック、アクセス制御、Payload API)に関する作業時に使用します。バリデーションエラー、セキュリティ問題、リレーションシップクエリ、トランザクション、フックの動作のデバッグにも活用できます。

description の原文を見る

Use when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.

SKILL.md 本文

Payload CMS アプリケーション開発

Payload は TypeScript ファーストアーキテクチャを備えた Next.js ネイティブ CMS で、管理パネル、データベース管理、REST/GraphQL API、認証、ファイルストレージを提供します。

クイックリファレンス

タスクソリューション詳細
スラッグの自動生成slugField()FIELDS.md#slug-field-helper
ユーザーごとにコンテンツを制限クエリを使用したアクセス制御ACCESS-CONTROL.md#row-level-security-with-complex-queries
Local API ユーザー操作user + overrideAccess: falseQUERIES.md#access-control-in-local-api
ドラフト/公開ワークフローversions: { drafts: true }COLLECTIONS.md#versioning--drafts
計算フィールドvirtual: trueフィールドレベルhooks.afterRead で値を返すFIELDS.md#virtual-fields
条件付きフィールドadmin.conditionFIELDS.md#conditional-fields
カスタムフィールド検証validate 関数FIELDS.md#validation
リレーションシップリストをフィルタフィールドの filterOptionsFIELDS.md#relationship
特定のフィールドを選択select パラメータQUERIES.md#field-selection
作成者/日付を自動設定beforeChange フックHOOKS.md#collection-hooks
フックループを防止req.context チェックHOOKS.md#context
カスケード削除beforeDelete フックHOOKS.md#collection-hooks
地理空間クエリpoint フィールドと near/withinFIELDS.md#point-geolocation
逆向きリレーションシップjoin フィールドタイプFIELDS.md#join-fields
Next.js リバリデーションafterChange でのコンテキスト制御HOOKS.md#nextjs-revalidation-with-context-control
リレーションシップでクエリネストされたプロパティ構文QUERIES.md#nested-properties
複雑なクエリAND/OR ロジックQUERIES.md#andor-logic
トランザクション操作に req を渡すADAPTERS.md#threading-req-through-operations
バックグラウンドジョブジョブキューとタスクADVANCED.md#jobs-queue
カスタム API ルートコレクションカスタムエンドポイントADVANCED.md#custom-endpoints
クラウドストレージストレージアダプタープラグインADAPTERS.md#storage-adapters
多言語対応localization 設定 + localized: trueADVANCED.md#localization
プラグインを作成(options) => (config) => ConfigPLUGIN-DEVELOPMENT.md#plugin-architecture
プラグインパッケージセットアップSWC を使用したパッケージ構造PLUGIN-DEVELOPMENT.md#plugin-package-structure
コレクションにフィールドを追加コレクションをマップ、フィールドをスプレッドPLUGIN-DEVELOPMENT.md#adding-fields-to-collections
プラグインフック配列内の既存フックを保持PLUGIN-DEVELOPMENT.md#adding-hooks
フィールドタイプをチェックタイプガード関数FIELD-TYPE-GUARDS.md

クイックスタート

npx create-payload-app@latest my-app
cd my-app
pnpm dev

最小限の設定

import { buildConfig } from 'payload'
import { mongooseAdapter } from '@payloadcms/db-mongodb'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
import path from 'path'
import { fileURLToPath } from 'url'

const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

export default buildConfig({
  admin: {
    user: 'users',
    importMap: {
      baseDir: path.resolve(dirname),
    },
  },
  collections: [Users, Media],
  editor: lexicalEditor(),
  secret: process.env.PAYLOAD_SECRET,
  typescript: {
    outputFile: path.resolve(dirname, 'payload-types.ts'),
  },
  db: mongooseAdapter({
    url: process.env.DATABASE_URL,
  }),
})

本質的なパターン

基本的なコレクション

import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
    defaultColumns: ['title', 'author', 'status', 'createdAt'],
  },
  fields: [
    { name: 'title', type: 'text', required: true },
    { name: 'slug', type: 'text', unique: true, index: true },
    { name: 'content', type: 'richText' },
    { name: 'author', type: 'relationship', relationTo: 'users' },
  ],
  timestamps: true,
}

より多くのコレクションパターン (認証、アップロード、ドラフト、ライブプレビュー) については、COLLECTIONS.md を参照してください。

共通フィールド

// テキストフィールド
{ name: 'title', type: 'text', required: true }

// リレーションシップ
{ name: 'author', type: 'relationship', relationTo: 'users', required: true }

// リッチテキスト
{ name: 'content', type: 'richText', required: true }

// セレクト
{ name: 'status', type: 'select', options: ['draft', 'published'], defaultValue: 'draft' }

// アップロード
{ name: 'image', type: 'upload', relationTo: 'media' }

すべてのフィールドタイプ (配列、ブロック、ポイント、結合、仮想、条件付きなど) については、FIELDS.md を参照してください。

フックの例

フックは 2 つのレベルのいずれかに存在し、相互交換はできません。コレクションフック{ doc, data, req, operation, ... } を受け取り、ドキュメント全体に作用します。フィールドフックは個別フィールドの hooks オブジェクト内に存在し、{ value, siblingData, ... } を受け取り、そのフィールドの新しい値を返します。計算/仮想フィールド、フィールドごとのフォーマッター、フィールドごとのアクセスマスキングはフィールドフックです。フィールド間のビジネスロジックはコレクションフックです。

// コレクションレベル: ドキュメント全体のビジネスロジック
export const Posts: CollectionConfig = {
  slug: 'posts',
  hooks: {
    beforeChange: [
      async ({ data, operation }) => {
        if (operation === 'create') {
          data.slug = slugify(data.title)
        }
        return data
      },
    ],
  },
  fields: [{ name: 'title', type: 'text' }],
}

// フィールドレベル: 単一フィールドの値を計算/フォーマット (仮想フィールドはこれを使用)
export const Users: CollectionConfig = {
  slug: 'users',
  fields: [
    { name: 'firstName', type: 'text' },
    { name: 'lastName', type: 'text' },
    {
      name: 'fullName',
      type: 'text',
      virtual: true,
      hooks: {
        afterRead: [({ siblingData }) => `${siblingData.firstName} ${siblingData.lastName}`],
      },
    },
  ],
}

「フィールドを計算する」または「フックでフィールドの値を入力する」と言われた場合は、そのフィールドのフィールドレベルフックを使用します。コレクションレベルの afterReaddoc を変更することはありません。

すべてのフックパターンについては HOOKS.md を参照してください。アクセス制御については ACCESS-CONTROL.md を参照してください。

タイプセーフなアクセス制御

import type { Access } from 'payload'
import type { User } from '@/payload-types'

// タイプセーフなアクセス制御
export const adminOnly: Access = ({ req }) => {
  const user = req.user as User
  return user?.roles?.includes('admin') || false
}

// 行レベルのアクセス制御
export const ownPostsOnly: Access = ({ req }) => {
  const user = req.user as User
  if (!user) return false
  if (user.roles?.includes('admin')) return true

  return {
    author: { equals: user.id },
  }
}

クエリの例

// Local API
const posts = await payload.find({
  collection: 'posts',
  where: {
    status: { equals: 'published' },
    'author.name': { contains: 'john' },
  },
  depth: 2,
  limit: 10,
  sort: '-createdAt',
})

// 入力されたリレーションシップを使用したクエリ
const post = await payload.findByID({
  collection: 'posts',
  id: '123',
  depth: 2, // リレーションシップを入力します (デフォルトは 2)
})
// 戻り値: { author: { id: "user123", name: "John" } }

// depth がない場合、リレーションシップは ID のみを返します
const post = await payload.findByID({
  collection: 'posts',
  id: '123',
  depth: 0,
})
// 戻り値: { author: "user123" }

すべてのクエリ演算子および REST/GraphQL の例については、QUERIES.md を参照してください。

Payload インスタンスの取得

// API ルート内 (Next.js)
import { getPayload } from 'payload'
import config from '@payload-config'

export async function GET() {
  const payload = await getPayload({ config })

  const posts = await payload.find({
    collection: 'posts',
  })

  return Response.json(posts)
}

// Server Components 内
import { getPayload } from 'payload'
import config from '@payload-config'

export default async function Page() {
  const payload = await getPayload({ config })
  const { docs } = await payload.find({ collection: 'posts' })

  return <div>{docs.map(post => <h1 key={post.id}>{post.title}</h1>)}</div>
}

セキュリティの落とし穴

1. Local API アクセス制御 (重大)

デフォルトでは、Local API 操作はすべてのアクセス制御をバイパスします。ユーザーを渡していても同じです。

// ❌ セキュリティバグ: ユーザーを渡していますが、権限は無視されます
await payload.find({
  collection: 'posts',
  user: someUser, // アクセス制御はバイパスされます!
})

// ✅ セキュア: ユーザーの権限を実際に強制します
await payload.find({
  collection: 'posts',
  user: someUser,
  overrideAccess: false, // アクセス制御に必須
})

各ケースの使い分け:

  • overrideAccess: true (デフォルト) - サーバー側の信頼できる操作 (cron ジョブ、システムタスク)
  • overrideAccess: false - ユーザーに代わって操作する場合 (API ルート、ウェブフック)

QUERIES.md#access-control-in-local-api を参照してください。

2. フック内のトランザクション失敗

req なしでフック内のネストされた操作はトランザクションのアトミック性を破壊します。

// ❌ データ破損のリスク: 別のトランザクション
hooks: {
  afterChange: [
    async ({ doc, req }) => {
      await req.payload.create({
        collection: 'audit-log',
        data: { docId: doc.id },
        // req がない - 別のトランザクションで実行されます!
      })
    },
  ]
}

// ✅ アトミック: 同じトランザクション
hooks: {
  afterChange: [
    async ({ doc, req }) => {
      await req.payload.create({
        collection: 'audit-log',
        data: { docId: doc.id },
        req, // アトミック性を維持します
      })
    },
  ]
}

ADAPTERS.md#threading-req-through-operations を参照してください。

3. 無限フックループ

フックが同じフックをトリガーする操作をトリガーすると、無限ループが発生します。

// ❌ 無限ループ
hooks: {
  afterChange: [
    async ({ doc, req }) => {
      await req.payload.update({
        collection: 'posts',
        id: doc.id,
        data: { views: doc.views + 1 },
        req,
      }) // afterChange を再度トリガーします!
    },
  ]
}

// ✅ セキュア: コンテキストフラグを使用
hooks: {
  afterChange: [
    async ({ doc, req, context }) => {
      if (context.skipHooks) return

      await req.payload.update({
        collection: 'posts',
        id: doc.id,
        data: { views: doc.views + 1 },
        context: { skipHooks: true },
        req,
      })
    },
  ]
}

HOOKS.md#context を参照してください。

プロジェクト構造

src/
├── app/
│   ├── (frontend)/
│   │   └── page.tsx
│   └── (payload)/
│       └── admin/[[...segments]]/page.tsx
├── collections/
│   ├── Posts.ts
│   ├── Media.ts
│   └── Users.ts
├── globals/
│   └── Header.ts
├── components/
│   └── CustomField.tsx
├── hooks/
│   └── slugify.ts
└── payload.config.ts

タイプ生成

// payload.config.ts
export default buildConfig({
  typescript: {
    outputFile: path.resolve(dirname, 'payload-types.ts'),
  },
  // ...
})

// 使用法
import type { Post, User } from '@/payload-types'

よくある落とし穴

  1. Local API がアクセス制御をバイパス - overrideAccess: false を渡さない限り
  2. ネストされた操作に req がない - トランザクションのアトミック性が破壊される
  3. フックループ - フック内の操作は同じフックを再トリガーできます。req.context フラグを使用してください
  4. フィールドレベルのアクセス - ブール値のみを返し、クエリ制約はありません
  5. リレーションシップの深さ - デフォルトは 2。ID のみの場合は depth: 0 を設定
  6. ドラフトステータス - ドラフトが有効な場合、_status フィールドは自動的に注入されます
  7. タイプが古い - generate:types を実行するまで
  8. MongoDB トランザクション - レプリカセット設定が必要です
  9. SQLite トランザクション - デフォルトで無効。transactionOptions: {} で有効化
  10. ポイントフィールド - SQLite ではサポートされていません

ベストプラクティス

セキュリティ

  • デフォルトは制限的、徐々に権限を追加
  • Local API に user を渡す場合は overrideAccess: false を使用
  • フィールドレベルのアクセスはブール値のみを返します (クエリ制約はありません)
  • クライアント提供のデータを信頼しない
  • saveToJWT: true をロール用に使用してデータベース検索を回避

パフォーマンス

  • 頻繁にクエリされるフィールドにインデックスを作成
  • select を使用して返されるフィールドを制限
  • リレーションシップで maxDepth を設定して過剰取得を防止
  • アクセス制御での async 操作よりもクエリ制約を優先
  • req.context で高コスト操作をキャッシュ

データ整合性

  • フック内のネストされた操作には常に req を渡す
  • 無限フックループを防ぐためにコンテキストフラグを使用
  • MongoDB (レプリカセット必須) と Postgres のトランザクションを有効化
  • データフォーマット用に beforeValidate を使用
  • ビジネスロジック用に beforeChange を使用

タイプセーフティ

  • スキーマ変更後に generate:types を実行
  • 生成された payload-types.ts からタイプをインポート
  • ユーザーオブジェクトを型指定: import type { User } from '@/payload-types'
  • ランタイム型チェック用にフィールドタイプガードを使用
  • 名前付き定数 (コレクション、フィールド、フック、アクセス関数、プラグインなど) に Payload タイプ (CollectionConfigFieldCollectionBeforeChangeHookAccessPlugin など) で注釈を付けるか、satisfies <Type> を使用してください。注釈がないと、type: 'text' のような文字列プロパティが string に拡張され、判別ユニオン (FieldCollectionConfig) が解決に失敗します。インライン リテラルはコンテキスト型付けにより無料で取得されます。抽出された定数はそうではありません。

組織

  • コレクションを別ファイルに保持
  • アクセス制御を access/ ディレクトリに抽出
  • フックを hooks/ ディレクトリに抽出
  • 共通パターン用の再利用可能なフィールドファクトリを使用
  • 複雑なアクセス制御をコメント付けで文書化

リファレンスドキュメント

  • FIELDS.md - すべてのフィールドタイプ、検証、管理オプション
  • FIELD-TYPE-GUARDS.md - ランタイムフィールドタイプチェックと型の絞り込み用のタイプガード
  • COLLECTIONS.md - コレクション設定、認証、アップロード、ドラフト、ライブプレビュー
  • HOOKS.md - コレクションフック、フィールドフック、コンテキストパターン
  • ACCESS-CONTROL.md - コレクション、フィールド、グローバルアクセス制御、RBAC、マルチテナント
  • ACCESS-CONTROL-ADVANCED.md - コンテキスト認識、時間ベース、サブスクリプション ベースのアクセス、ファクトリ関数、テンプレート
  • QUERIES.md - クエリ演算子、Local/REST/GraphQL API
  • ENDPOINTS.md - カスタム API エンドポイント: 認証、ヘルパー、リクエスト/レスポンスパターン
  • ADAPTERS.md - データベース、ストレージ、メールアダプター、トランザクション
  • ADVANCED.md - 認証、ジョブ、エンドポイント、コンポーネント、プラグイン、ローカライゼーション
  • PLUGIN-DEVELOPMENT.md - プラグインアーキテクチャ、モノレポ構造、パターン、ベストプラクティス

リソース

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
payloadcms
リポジトリ
payloadcms/payload
ライセンス
MIT
最終更新
不明

Source: https://github.com/payloadcms/payload / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: payloadcms · payloadcms/payload · ライセンス: MIT