payload

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Payload CMS Operations

Payload CMS 操作指南

Manage Payload CMS content via REST API. Works with any Payload deployment (production or local).
通过REST API管理Payload CMS内容。适用于任何Payload部署环境(生产环境或本地环境)。

When to Use

适用场景

  • Creating or editing posts/pages in Payload CMS
  • Converting markdown content to Lexical rich text format
  • Listing and querying Payload collections
  • Bulk content updates
  • 在Payload CMS中创建或编辑帖子/页面
  • 将Markdown内容转换为Lexical富文本格式
  • 列出和查询Payload集合
  • 批量内容更新

Workflow: REST API with Authentication

工作流:带身份验证的REST API

Step 1: Determine the API Endpoint

步骤1:确定API端点

Ask the user for their Payload site URL, or check common locations:
bash
undefined
向用户询问其Payload站点URL,或检查常见地址:
bash
undefined

Production site (ask user or check project config)

生产站点(询问用户或检查项目配置)

Local development

本地开发环境

curl -s "http://localhost:3000/api/posts?limit=1" 2>/dev/null | head -c 100 curl -s "http://localhost:3010/api/posts?limit=1" 2>/dev/null | head -c 100
undefined
curl -s "http://localhost:3000/api/posts?limit=1" 2>/dev/null | head -c 100 curl -s "http://localhost:3010/api/posts?limit=1" 2>/dev/null | head -c 100
undefined

Step 2: Authenticate

步骤2:身份验证

For mutations (create/update/delete), authentication is required. Payload uses session-based auth.
Option A: User provides credentials
bash
undefined
对于创建/更新/删除等变更操作,需要身份验证。Payload使用基于会话的身份验证。
选项A:用户提供凭据
bash
undefined

Login to get auth token

登录获取认证令牌

curl -X POST "https://your-site.com/api/users/login"
-H "Content-Type: application/json"
-d '{"email": "user@example.com", "password": "..."}'
-c cookies.txt
curl -X POST "https://your-site.com/api/users/login"
-H "Content-Type: application/json"
-d '{"email": "user@example.com", "password": "..."}'
-c cookies.txt

Use the cookie file for authenticated requests

使用Cookie文件进行已认证请求

curl -X POST "https://your-site.com/api/posts"
-H "Content-Type: application/json"
-b cookies.txt
-d '{"title": "...", "content": {...}}'

**Option B: User logs in via admin UI**
Have the user log in at `/admin`, then extract the `payload-token` cookie from their browser for use in API calls.
curl -X POST "https://your-site.com/api/posts"
-H "Content-Type: application/json"
-b cookies.txt
-d '{"title": "...", "content": {...}}'

**选项B:用户通过管理UI登录**
让用户在`/admin`路径登录,然后从其浏览器中提取`payload-token` Cookie用于API调用。

Step 3: Create/Update Content

步骤3:创建/更新内容

bash
undefined
bash
undefined

Create a post

创建帖子

curl -X POST "https://your-site.com/api/posts"
-H "Content-Type: application/json"
-b cookies.txt
-d '{ "title": "Post Title", "slug": "post-slug", "content": { "root": { ... } }, "_status": "published" }'
curl -X POST "https://your-site.com/api/posts"
-H "Content-Type: application/json"
-b cookies.txt
-d '{ "title": "帖子标题", "slug": "post-slug", "content": { "root": { ... } }, "_status": "published" }'

Update a post

更新帖子

curl -X PATCH "https://your-site.com/api/posts/POST_ID"
-H "Content-Type: application/json"
-b cookies.txt
-d '{"content": { "root": { ... } }}'
undefined
curl -X PATCH "https://your-site.com/api/posts/POST_ID"
-H "Content-Type: application/json"
-b cookies.txt
-d '{"content": { "root": { ... } }}'
undefined

Step 4: Verify

步骤4:验证

bash
undefined
bash
undefined

Check the post was created

检查帖子是否创建成功

curl -s "https://your-site.com/api/posts?where[slug][equals]=post-slug" | jq '.docs[0]'
undefined
curl -s "https://your-site.com/api/posts?where[slug][equals]=post-slug" | jq '.docs[0]'
undefined

Lexical JSON Structure

Lexical JSON结构

Payload's Lexical editor stores content as JSON:
json
{
  "root": {
    "type": "root",
    "format": "",
    "indent": 0,
    "version": 1,
    "direction": "ltr",
    "children": [
      {
        "type": "paragraph",
        "format": "",
        "indent": 0,
        "version": 1,
        "direction": "ltr",
        "children": [
          {"type": "text", "text": "Content here", "mode": "normal", "format": 0, "detail": 0, "version": 1, "style": ""}
        ]
      }
    ]
  }
}
Payload的Lexical编辑器以JSON格式存储内容:
json
{
  "root": {
    "type": "root",
    "format": "",
    "indent": 0,
    "version": 1,
    "direction": "ltr",
    "children": [
      {
        "type": "paragraph",
        "format": "",
        "indent": 0,
        "version": 1,
        "direction": "ltr",
        "children": [
          {"type": "text", "text": "内容示例", "mode": "normal", "format": 0, "detail": 0, "version": 1, "style": ""}
        ]
      }
    ]
  }
}

Supported Node Types

支持的节点类型

MarkdownLexical Node
Paragraphs
paragraph
# Heading
heading
with tag h1-h6
**bold**
text with format: 1
*italic*
text with format: 2
`code`
text with format: 16
Code blocks
block
with blockType: "code"
Lists
list
with
listitem
children
> quotes
quote
MarkdownLexical 节点
段落
paragraph
# 标题
heading
(标签为h1-h6)
**粗体**
format值为1的文本
*斜体*
format值为2的文本
`代码`
format值为16的文本
代码块blockType为"code"的
block
列表包含
listitem
子节点的
list
> 引用
quote

Text Format Bitmask

文本格式位掩码

ValueFormat
0Normal
1Bold
2Italic
3Bold + Italic
16Code
数值格式
0普通文本
1粗体
2斜体
3粗体+斜体
16代码

Markdown to Lexical Conversion

Markdown转Lexical格式

The skill includes a Python script for converting markdown to Lexical JSON:
bash
python3 ${SKILL_DIR}/scripts/md_to_lexical.py article.md > /tmp/content.json
此Skill包含一个将Markdown转换为Lexical JSON的Python脚本:
bash
python3 ${SKILL_DIR}/scripts/md_to_lexical.py article.md > /tmp/content.json

Common Collections

常见集合

CollectionSlugPurpose
Posts
posts
Blog posts
Pages
pages
Static pages
Media
media
Uploaded files
Users
users
User accounts
集合别名用途
Posts
posts
博客帖子
Pages
pages
静态页面
Media
media
上传文件
Users
users
用户账户

Local Development Alternative

本地开发替代方案

If working locally and REST auth is problematic, write an inline script in the project:
typescript
// scripts/create-post.ts
import { getPayload } from 'payload'
import config from '../src/payload.config'

const payload = await getPayload({ config })
await payload.create({
  collection: 'posts',
  data: { title: '...', content: {...}, _status: 'published' }
})
process.exit(0)
Run with:
source .env.local && bunx tsx scripts/create-post.ts
Note: If Drizzle prompts for schema migration, answer 'n' and use REST API instead.
如果在本地开发时REST身份验证存在问题,可以在项目中编写内联脚本:
typescript
// scripts/create-post.ts
import { getPayload } from 'payload'
import config from '../src/payload.config'

const payload = await getPayload({ config })
await payload.create({
  collection: 'posts',
  data: { title: '...', content: {...}, _status: 'published' }
})
process.exit(0)
运行命令:
source .env.local && bunx tsx scripts/create-post.ts
注意:如果Drizzle提示进行 schema 迁移,请输入'n'并改用REST API。

Payload CLI Commands

Payload CLI命令

The Payload CLI provides comprehensive database and project management:
Payload CLI提供全面的数据库和项目管理功能:

Migration Commands

迁移命令

bash
undefined
bash
undefined

Check migration status

检查迁移状态

bun run payload migrate:status
bun run payload migrate:status

Run pending migrations

运行待处理的迁移

bun run payload migrate
bun run payload migrate

Create a new migration

创建新迁移

bun run payload migrate:create migration-name
bun run payload migrate:create migration-name

Rollback last migration

回滚上一次迁移

bun run payload migrate:down
bun run payload migrate:down

Rollback and re-run all migrations

回滚并重新运行所有迁移

bun run payload migrate:refresh
bun run payload migrate:refresh

Reset all migrations (rollback everything)

重置所有迁移(回滚全部)

bun run payload migrate:reset
bun run payload migrate:reset

Fresh start - drop all tables and re-run migrations

全新启动 - 删除所有表并重新运行迁移

bun run payload migrate:fresh
undefined
bun run payload migrate:fresh
undefined

Generation Commands

生成命令

bash
undefined
bash
undefined

Generate TypeScript types from collections

从集合生成TypeScript类型

bun run payload generate:types
bun run payload generate:types

Generate import map

生成导入映射

bun run payload generate:importmap
bun run payload generate:importmap

Generate Drizzle database schema

生成Drizzle数据库schema

bun run payload generate:db-schema
undefined
bun run payload generate:db-schema
undefined

Utility Commands

实用命令

bash
undefined
bash
undefined

Show Payload project info

显示Payload项目信息

bun run payload info
bun run payload info

Run a custom script with Payload initialized

在Payload初始化后运行自定义脚本

bun run payload run scripts/my-script.ts
undefined
bun run payload run scripts/my-script.ts
undefined

Jobs Commands (if using Payload Jobs)

任务命令(若使用Payload Jobs)

bash
undefined
bash
undefined

Run queued jobs

运行队列中的任务

bun run payload jobs:run
bun run payload jobs:run

Run jobs with options

带选项运行任务

bun run payload jobs:run --limit 10 --queue default
bun run payload jobs:run --limit 10 --queue default

Handle scheduled jobs

处理定时任务

bun run payload jobs:handle-schedules
undefined
bun run payload jobs:handle-schedules
undefined

Database Security (RLS)

数据库安全(RLS)

CRITICAL: Payload uses application-level access control by default. For production security, implement Row Level Security (RLS) at the database level:
关键提示:Payload默认使用应用级别的访问控制。为了生产环境安全,请在数据库层面实现行级安全(Row Level Security,RLS):

Why RLS Matters

RLS的重要性

  • Application-level filtering can be bypassed with direct database connections
  • RLS enforces security at the database level
  • Even table owners cannot bypass RLS when
    FORCE ROW LEVEL SECURITY
    is enabled
  • 应用级别的过滤可以通过直接数据库连接绕过
  • RLS在数据库层面强制实施安全策略
  • 当启用
    FORCE ROW LEVEL SECURITY
    时,即使表所有者也无法绕过RLS

RLS Migration Template

RLS迁移模板

Create a migration for user-data tables:
typescript
// src/migrations/YYYYMMDDHHMMSS_enable_rls.ts
import { type MigrateUpArgs, type MigrateDownArgs, sql } from "@payloadcms/db-postgres";

export async function up({ db }: MigrateUpArgs): Promise<void> {
  // Helper function to check admin status
  await db.execute(sql`
    CREATE OR REPLACE FUNCTION is_admin()
    RETURNS BOOLEAN
    LANGUAGE SQL
    STABLE
    SECURITY DEFINER
    AS $$
      SELECT COALESCE(
        CURRENT_SETTING('app.current_user_role', TRUE) = 'admin',
        FALSE
      );
    $$;
  `);

  // Enable RLS on sensitive tables
  await db.execute(sql`
    ALTER TABLE users ENABLE ROW LEVEL SECURITY;
    ALTER TABLE users FORCE ROW LEVEL SECURITY;
    
    -- Users can only access their own data
    CREATE POLICY users_select_policy ON users
      FOR SELECT USING (id = (SELECT get_current_user_id()) OR (SELECT is_admin()));
    
    CREATE POLICY users_update_policy ON users
      FOR UPDATE USING (id = (SELECT get_current_user_id()) OR (SELECT is_admin()));
  `);
}

export async function down({ db }: MigrateDownArgs): Promise<void> {
  await db.execute(sql`DROP FUNCTION IF EXISTS is_admin();`);
  await db.execute(sql`ALTER TABLE users DISABLE ROW LEVEL SECURITY;`);
}
为用户数据表创建迁移:
typescript
// src/migrations/YYYYMMDDHHMMSS_enable_rls.ts
import { type MigrateUpArgs, type MigrateDownArgs, sql } from "@payloadcms/db-postgres";

export async function up({ db }: MigrateUpArgs): Promise<void> {
  // 检查管理员状态的辅助函数
  await db.execute(sql`
    CREATE OR REPLACE FUNCTION is_admin()
    RETURNS BOOLEAN
    LANGUAGE SQL
    STABLE
    SECURITY DEFINER
    AS $$
      SELECT COALESCE(
        CURRENT_SETTING('app.current_user_role', TRUE) = 'admin',
        FALSE
      );
    $$;
  `);

  // 为敏感表启用RLS
  await db.execute(sql`
    ALTER TABLE users ENABLE ROW LEVEL SECURITY;
    ALTER TABLE users FORCE ROW LEVEL SECURITY;
    
    -- 用户只能访问自己的数据
    CREATE POLICY users_select_policy ON users
      FOR SELECT USING (id = (SELECT get_current_user_id()) OR (SELECT is_admin()));
    
    CREATE POLICY users_update_policy ON users
      FOR UPDATE USING (id = (SELECT get_current_user_id()) OR (SELECT is_admin()));
  `);
}

export async function down({ db }: MigrateDownArgs): Promise<void> {
  await db.execute(sql`DROP FUNCTION IF EXISTS is_admin();`);
  await db.execute(sql`ALTER TABLE users DISABLE ROW LEVEL SECURITY;`);
}

Tables Requiring RLS

需要RLS的表

  • users
    - User profiles and sensitive data
  • api_keys
    - API credentials
  • deposits
    - Financial transaction data
  • usage_logs
    - Audit trails and usage data
  • Any table with user-specific data
  • users
    - 用户资料和敏感数据
  • api_keys
    - API凭据
  • deposits
    - 金融交易数据
  • usage_logs
    - 审计日志和使用数据
  • 任何包含用户特定数据的表

Performance Optimization

性能优化

  • Always add indexes on columns used in RLS policies (e.g.,
    user_id
    )
  • Use
    (SELECT function())
    pattern for caching auth checks per query
  • Create helper functions with
    SECURITY DEFINER
    for complex logic
  • 始终为RLS策略中使用的列添加索引(例如
    user_id
  • 使用
    (SELECT function())
    模式为每个查询缓存身份验证检查
  • 为复杂逻辑创建带
    SECURITY DEFINER
    的辅助函数

Migration Workflows

迁移工作流

Development Mode vs Migrations

开发模式 vs 迁移模式

Development Mode (Push):
  • Automatic schema updates via
    push: true
    (default)
  • Good for rapid prototyping
  • NOT for production
Migration Mode:
  • Explicit schema control via migration files
  • Required for production databases
  • Version-controlled schema changes
开发模式(Push)
  • 通过
    push: true
    自动更新schema(默认设置)
  • 适合快速原型开发
  • 禁止在生产环境使用
迁移模式
  • 通过迁移文件显式控制schema
  • 生产数据库必需
  • schema变更受版本控制

Typical Workflow

典型工作流

  1. Develop locally with push mode (default)
    • Make changes to Payload config
    • Drizzle automatically pushes changes to local DB
  2. Create migration when feature is complete
    bash
    bun run payload migrate:create feature-name
  3. Review generated migration before committing
  4. Run migrations in production before deployment
    bash
    # In CI/CD pipeline
    bun run payload migrate && bun run build
  1. 在本地使用push模式开发(默认)
    • 修改Payload配置
    • Drizzle自动将变更推送到本地数据库
  2. 功能完成后创建迁移
    bash
    bun run payload migrate:create feature-name
  3. 提交前审查生成的迁移文件
  4. 部署前在生产环境运行迁移
    bash
    # 在CI/CD流水线中执行
    bun run payload migrate && bun run build

Migration Sync Issues

迁移同步问题

If you get "dev mode" warnings when running migrations:
bash
undefined
如果运行迁移时出现「开发模式」警告:
bash
undefined

Mark existing migrations as already run

将现有迁移标记为已执行

psql "$DATABASE_URL" -c " INSERT INTO payload_migrations (name, batch, created_at, updated_at) SELECT * FROM (VALUES ('20250101_000000_migration_name', 1, NOW(), NOW()) ) AS v(name, batch, created_at, updated_at) WHERE NOT EXISTS ( SELECT 1 FROM payload_migrations WHERE name = v.name ); "
undefined
psql "$DATABASE_URL" -c " INSERT INTO payload_migrations (name, batch, created_at, updated_at) SELECT * FROM (VALUES ('20250101_000000_migration_name', 1, NOW(), NOW()) ) AS v(name, batch, created_at, updated_at) WHERE NOT EXISTS ( SELECT 1 FROM payload_migrations WHERE name = v.name ); "
undefined

Project Maintenance

项目维护

Dependency Updates

依赖更新

bash
undefined
bash
undefined

Check for outdated packages

检查过时的包

bun outdated
bun outdated

Update specific packages

更新特定包

bun update package-name
bun update package-name

Update all packages

更新所有包

bun update
undefined
bun update
undefined

Type Generation

类型生成

After modifying collections or globals:
bash
bun run generate:types
修改集合或全局配置后:
bash
bun run generate:types

Database Connection

数据库连接

Payload uses connection pooling. Common connection strings:
  • DATABASE_URI
    - Primary connection (often pooled)
  • POSTGRES_URL_NON_POOLING
    - Direct connection for migrations
Payload使用连接池。常见连接字符串:
  • DATABASE_URI
    - 主连接(通常为池化连接)
  • POSTGRES_URL_NON_POOLING
    - 用于迁移的直接连接

Troubleshooting

故障排除

Migration timeout: Use non-pooled connection string
bash
undefined
迁移超时:使用非池化连接字符串
bash
undefined

Use POSTGRES_URL_NON_POOLING for migrations

为迁移使用POSTGRES_URL_NON_POOLING

DATABASE_URL=$(grep POSTGRES_URL_NON_POOLING .env.local | cut -d'"' -f2)

**Drizzle schema prompts**: Answer 'n' to avoid conflicts with migrations

**Type errors after updates**: Run `bun run generate:types`
DATABASE_URL=$(grep POSTGRES_URL_NON_POOLING .env.local | cut -d'"' -f2)

**Drizzle schema提示**:输入'n'以避免与迁移冲突

**更新后类型错误**:运行`bun run generate:types`

Additional Resources

额外资源

  • references/lexical-format.md
    - Complete Lexical node type reference
  • references/rest-api.md
    - Full REST API documentation
  • references/database-security.md
    - RLS and security best practices
  • scripts/md_to_lexical.py
    - Markdown to Lexical converter
  • scripts/create-post.ts
    - Example local API script
  • Payload Docs: https://payloadcms.com/docs
  • references/lexical-format.md
    - 完整的Lexical节点类型参考
  • references/rest-api.md
    - 完整的REST API文档
  • references/database-security.md
    - RLS和安全最佳实践
  • scripts/md_to_lexical.py
    - Markdown转Lexical转换器
  • scripts/create-post.ts
    - 本地API脚本示例
  • Payload官方文档https://payloadcms.com/docs