学习,学习,再学习!学,然后知不足。——列宁

Payload:把全栈能力放进 Next.js 应用里的开源框架

项目地址:https://github.com/payloadcms/payload

内容管理系统常常被想象成一处后台入口:编辑内容、上传媒体、管理用户、发布页面。可当一个项目真正开始生长,内容管理、应用逻辑、权限体系、数据模型、前端展示与部署方式往往很难再被整齐地切开。

Payload 选择把这些环节带到同一片开发空间中。

它是一个开源的全栈 Next.js 框架,能够立即提供 TypeScript 后端与管理面板。它可以作为 Headless CMS 使用,也可以用于构建功能更完整的应用。它强调原生运行在 Next.js 中,并且能够直接安装进现有项目的 /app 目录。

这意味着,内容并不一定要住在一个遥远、独立、封闭的后台系统里。它可以和前端页面、服务端逻辑、React Server Components 以及项目自身的数据模型靠得更近。

CMS 不只是后台,也可以成为应用框架的一部分

Payload 的核心思路很明确:它既是应用框架,也是 Headless CMS。

传统 CMS 往往将后台、接口与前端项目分隔开来。Payload 则允许开发者在同一个 /app 目录中组织前端与后端。项目可以在 Next.js 的应用结构中继续向前生长,同时获得管理后台、数据模型、认证、权限控制、内容版本与草稿等能力。

它不是将内容管理塞进一个固定的盒子,而是让内容管理能力成为应用的一部分。

在这种方式下,开发者可以直接在 React Server Components 中查询数据库,而不一定需要通过 REST 或 GraphQL 中转。前端与后端不再是两段需要不断对接的独立旅程,而可以在同一套 TypeScript 项目中协同运行。

让 TypeScript 覆盖从数据到界面的路径

Payload 是完全基于 TypeScript 的。

数据模型拥有自动生成的类型,后端逻辑、管理面板扩展与应用代码可以围绕同一种语言组织。对于希望减少类型断层的项目而言,这种一致性让数据定义不再只是数据库层的细节,也能成为应用开发时可被直接使用的类型基础。

内容模型并不只是“有哪些字段”的清单。

它可以进一步参与权限判断、管理后台界面、服务端查询、数据钩子、接口输出与前端渲染。字段、集合、用户身份与业务逻辑能够被编织在同一个全栈项目中。

Payload 让类型不只是编辑器里的提示,而是贯穿数据和应用的一条线。

从一条命令开始创建项目

Payload 提供了项目创建命令:

1
pnpx create-payload-app@latest

对于首次接触 Payload 的项目,README 推荐从网站模板开始:

1
pnpx create-payload-app@latest -t website

网站模板展示了多项实践内容,包括自定义富文本块、按需重新验证、动态内容驱动页面与即时预览。

如果希望基于已有示例创建项目,也可以使用:

1
npx create-payload-app --example example_name

这种创建方式让不同起点拥有各自的入口。可以从通用项目开始,也可以直接进入网站、电商或具体功能示例所准备的结构中。

在 /app 中运行的内容管理体验

Payload 的一个重要特征,是它可以原生运行在 Next.js 应用结构中。

它强调可以直接安装到既有的 /app 文件夹中,并支持通过 Server Components 扩展 Payload 的界面。管理后台与后端都可以进行扩展,开发者能够围绕自己的应用需求继续塑造界面、逻辑与数据交互。

这使管理面板不必是一块无法触碰的固定区域。

字段可以拥有自定义界面,集合可以拥有自定义视图,根级管理界面也可以加入新的区域或设置入口。管理后台不只是用于录入内容的地方,也可以随着产品需求改变形态。

Payload 的可扩展性覆盖管理端与后端两侧。前者可以围绕编辑体验与运营需求延展,后者则可以围绕数据、权限、钩子与业务规则继续深入。

内容模型之外,还有认证与身份

许多应用在需要内容管理之后,很快也会需要用户体系。

Payload 提供开箱即用的认证能力。用户集合可以启用身份验证,并通过角色区分不同用户可以执行的操作。

在认证示例中,用户集合能够同时承载管理员与普通用户。管理员可以进入管理面板并管理应用内容,普通用户则根据身份拥有受限的操作权限。

服务端可以通过 Local API 获取用户与权限信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { headers as getHeaders } from 'next/headers.js'
import { getPayload } from 'payload'
import config from '../../payload.config'

export default async function AccountPage() {
const headers = await getHeaders()
const payload = await getPayload({ config })
const { permissions, user } = await payload.auth({ headers })

if (!user) {
return null
}

return {
permissions,
user,
}
}

认证相关能力也可以通过 HTTP 层暴露出来,覆盖当前用户信息、登录、退出、刷新令牌、验证邮箱、解锁账户、忘记密码与重置密码等操作。

1
2
3
4
5
6
7
await fetch('/api/users/me', {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
})

内容与用户并不总是两套平行系统。Payload 让它们可以在同一个框架里被定义、控制与使用。

权限控制可以细到每一层

Payload 提供非常细粒度的访问控制能力。

权限并不只停留在“能否访问后台”这一层。数据集合、字段与操作都可以进入权限设计范围。不同身份的用户可以拥有不同的数据可见性与操作边界。

在认证示例中,角色可以决定用户能否访问管理面板。管理员拥有完整的管理能力,普通用户则基于自身身份受到操作限制。

字段级钩子还能在数据变化前介入。例如,示例中使用 beforeChange 字段钩子保护角色字段,使新用户自动获得普通用户角色,并避免角色被未经授权地修改。

权限控制因此不只是一个登录后的开关,而可以持续参与数据生命周期。

版本、草稿与内容变化的轨迹

内容并不总是一次完成。

一篇文章可能会经历撰写、修改、审阅与发布。一组页面配置可能需要保存多个阶段。一个复杂内容模型也可能需要保留每次变动留下的痕迹。

Payload 提供版本与草稿能力,让内容变化可以拥有更清晰的轨迹。

草稿让未完成内容不必立刻以最终状态出现。版本则让内容的不同阶段得以保存。对于持续编辑的内容项目而言,内容不再只有“存在”或“不存在”两种状态,而可以拥有自己的演进过程。

富文本、区块与可组合页面

内容并不总是由标题和正文构成。

页面往往需要横幅、图文区域、卡片、行动区域、媒体模块、复杂排版与不同类型的内容片段。Payload 提供基于区块的布局构建能力,让页面结构能够由不同内容块组合而成。

同时,它提供 Lexical 富文本编辑器。富文本能力可以承载比普通文本更丰富的内容表达,区块系统则可以让页面以更灵活的方式被拼装。

网站模板展示了自定义富文本块与动态内容驱动页面的实践方向。内容不只是在编辑器里被写下,也可以成为页面结构的一部分。

当内容模型与展示结构都能够组合时,页面便不必被固定模板牢牢限制。

条件字段与更贴近业务的数据录入

表单并不一定应该对所有人展示同样的字段。

不同选择可能带来不同后续输入,不同内容类型也可能需要不同配置。Payload 提供条件字段逻辑,让字段能够根据数据状态决定是否显示。

这使后台录入界面可以更贴近业务本身。

某些字段可以只在特定情况下出现,某些配置可以随着选择变化而展开。内容编辑不必面对一张永远不变、不断增长的长表单,而可以拥有更具上下文的交互方式。

钩子让数据流程拥有介入点

Payload 提供文档级与字段级钩子,可以覆盖它所提供的各类操作。

钩子为数据流程提供了介入位置。创建、更新或其他行为发生时,业务逻辑可以在对应阶段参与进来。

这让数据模型不只是静态定义。

它可以在数据变动前补充默认值,可以在变动过程中保护关键字段,也可以围绕具体操作执行项目所需要的逻辑。内容管理系统由此不只是数据录入工具,也可以成为业务流程的一部分。

自定义组件,让管理后台继续生长

Payload 的管理后台建立在 React 之上,并且可以被自定义。

自定义组件示例展示了如何使用自定义 UI 元素扩展管理面板。集合中的字段可以配置自定义组件,管理端界面可以按不同插槽进行扩展,集合级视图可以呈现自定义标签页或布局,根级视图则可以进一步调整全局管理界面。

这意味着后台并不只有一种标准模样。

字段可以根据业务需要拥有不同的交互,数据展示方式可以调整,管理端也可以出现新的区域和入口。对于有特定运营流程、复杂编辑需求或内部管理界面的项目,后台可以逐渐贴近产品自身的工作方式。

数据库、媒体与部署可以走向不同环境

Payload 支持以不同方式部署。

README 中提供了 Cloudflare 与 Vercel 的一键部署方向。

在 Cloudflare 的部署方案中,可以结合 Workers、R2 与 D1。Workers 用于运行,R2 用于上传文件,D1 作为全球复制的数据库。

在 Vercel 的部署方案中,可以将 Next.js 前端、Neon 数据库与 Vercel Blob 媒体存储组合起来。

Payload 强调可以部署到不同环境,也可以部署为运行在 Vercel 上的无服务器应用。它不要求项目必须进入特定托管模式,而是为不同部署路径保留了入口。

模板不是起点的装饰,而是完整项目的骨架

Payload 提供一键模板,用于帮助项目快速启动。

README 中列出了网站模板与电商模板,并将这些模板描述为面向生产环境的端到端解决方案。它们的目标是让开发者能够更快进入实际产品构建,而不是只得到一个空白项目。

网站模板覆盖内容页面与富文本块等方向。

电商模板则为构建电商商店提供了另一种起点。

模板的意义不只是把几个页面放在一起,而是让内容、数据、界面与应用结构从一开始就拥有可以继续扩展的形态。

插件让功能可以进入,也可以离开

Payload 支持安装和分发插件。

插件可以增加或移除功能,既有官方支持的插件,也有社区支持的插件。项目不必把所有功能预先固定在核心中,而可以根据需求组合自己的能力边界。

这种扩展方式让 Payload 更像一个可继续搭建的平台。

应用需要什么能力,就可以围绕它寻找或构建相应插件。功能不必只能从一开始就被写死在项目里,也可以通过插件机制进入开发流程。

安全能力不是事后的补丁

Payload README 中提到,它通过 HTTP Only Cookie、CSRF 防护等机制提供安全保障。

认证、访问控制与安全措施共同构成了后端能力的一部分。用户身份决定谁可以访问什么,访问控制决定数据操作的边界,HTTP Only Cookie 与 CSRF 防护则为请求与会话提供额外保护。

这让安全不只是发布前才匆忙补上的清单,而是可以和内容模型、用户体系、后台访问一起被纳入项目结构。

用示例探索不同的项目形态

Payload 仓库提供了多个示例。

认证示例展示了用户认证、角色权限、Local API、HTTP 操作、数据库配置与种子数据相关内容。

自定义组件示例展示了如何将自定义 UI 组件带入管理后台,如何扩展字段、集合视图与根级视图。

这些示例可以通过项目创建命令生成:

1
npx create-payload-app --example auth

或者:

1
npx create-payload-app --example custom-components

示例提供的并不只是单一功能片段,而是把配置、数据模型、运行方式与管理后台放进能够启动的项目结构里。

一个更靠近应用本身的 CMS

Payload 的特别之处,在于它没有把 CMS 放在应用之外。

它让内容管理与 Next.js 项目靠在一起,让前端与后端能够共享同一片 /app 空间,让 TypeScript 类型从数据模型延伸到应用逻辑,让认证、权限、版本、草稿、富文本、区块、钩子、自定义后台与插件机制共同构成项目能力。

它可以作为 Headless CMS,也可以用于构建更完整的应用。

内容不再只是等待被展示的数据,后台也不再只是一个与产品脱节的独立区域。它们可以和页面、接口、用户、权限与服务端逻辑一起生长,成为全栈应用内部持续运转的一部分。