使用服务器 API 管理 Framer CMS——列出、创建、读取、更新和删除 CMS 集合和条目,上传图片,发布预览,部署到生产环境
帧器 CMS — 服务器 API 技能. 管理帧器 CMS 内容程序化通过帧器- api npm 包. 推送文章,上传图像,创建收藏,以及发布/部署 —— 全部
功能概述
帧器 CMS — 服务器 API 技能. 管理帧器 CMS 内容程序化通过帧器- api npm 包. 推送文章,上传图像,创建收藏,以及发布/部署 —— 全部是一项面向实际任务的技能。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
核心要点
- 使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。
- 该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。
- 从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。
使用与执行
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
结果检查与注意事项
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
Framer CMS — Server API 技能
通过 framer-api npm 包以编程方式管理 Framer CMS 内容。可推送文章、上传图片、创建集合(collection),以及发布(publish)/部署(deploy)——全部可通过终端完成,无需打开 Framer 应用。
首次设置(入门流程)
若用户在当前项目中首次使用该技能,请运行 references/onboarding.md 中描述的入门流程。
快速检查:查看用户的 .env 文件或环境变量中是否存在 FRAMER_PROJECT_URL 和 FRAMER_API_KEY。若缺失,请执行入门流程。
工作原理
本技能基于 Framer Server API(即 framer-api npm 包),该包通过 WebSocket 使用 API 密钥连接至 Framer 项目,提供完整的 CMS 增删改查(CRUD)、图片上传、发布与部署能力。
重要提示:项目中必须已安装 framer-api 包。若未安装,请运行:
npm i framer-api
所有操作均通过 ES 模块脚本(.mjs 文件)实现,并采用如下连接模式:
import { connect } from "framer-api"
// 重要:API 密钥需以纯字符串形式传入(第二个参数),而非 {apiKey: "..."}
const framer = await connect(process.env.FRAMER_PROJECT_URL, process.env.FRAMER_API_KEY)
try {
// ... 执行操作 ...
} finally {
await framer.disconnect()
}
可用操作
CMS 集合(Collections)
| 操作 | 方法 | 说明 |
|---|---|---|
| 列出所有集合 | framer.getCollections() |
返回全部 CMS 集合 |
| 获取单个集合 | framer.getCollection(id) |
根据集合 ID 获取 |
| 创建集合 | framer.createCollection(name) |
创建空集合 |
| 获取字段定义 | collection.getFields() |
返回字段定义(name、type、id) |
| 添加字段 | collection.addFields([{type, name}]) |
向集合中添加新字段 |
| 删除字段 | collection.removeFields([fieldId]) |
根据字段 ID 删除字段 |
| 重排字段顺序 | collection.setFieldOrder([fieldIds]) |
设置字段在编辑器中的显示顺序 |
CMS 条目(Items,如文章、记录)
| 操作 | 方法 | 说明 |
|---|---|---|
| 列出所有条目 | collection.getItems() |
返回全部条目及其字段数据 |
| 创建条目 | collection.addItems([{slug, fieldData}]) |
创建新条目。返回值为 undefined —— 需调用 getItems() 重新获取以获得条目 ID |
| 更新条目字段 | item.setAttributes({ fieldData: { [fieldId]: {type, value} } }) |
必须将字段值包裹在 fieldData: 中;否则值将被静默忽略,不报错 |
| 更新条目 slug 或草稿状态 | item.setAttributes({ slug: "new", draft: false }) |
slug 和 draft 属性直接设置(不在 fieldData 内) |
| 删除单个条目 | item.remove() |
仅删除一个条目 |
| 批量删除条目 | collection.removeItems([itemIds]) |
一次删除多个条目 |
| 重排条目顺序 | collection.setItemOrder([itemIds]) |
设置条目在编辑器中的显示顺序 |
⚠️ 关键提示:如何更新 CMS 条目字段
setAttributes 方法具有 非直观的 API 设计 —— 字段值 必须 包裹在 fieldData 键下:
// ✅ 正确 —— 字段值包裹在 fieldData 中
await item.setAttributes({
fieldData: {
[titleFieldId]: { type: "string", value: "New Title" }
}
})
// ❌ 错误 —— 值将被静默忽略,且不抛出错误
await item.setAttributes({
[titleFieldId]: { type: "string", value: "New Title" }
})
// ❌ 错误 —— 同样会被静默忽略
await item.setAttributes({
[titleFieldId]: "New Title"
})
支持部分更新:仅修改指定字段,其余字段保持不变。
非字段属性(如 slug、draft)应直接设于对象顶层,而非置于 fieldData 内:
await item.setAttributes({ slug: "new-slug", draft: false })
字段数据格式
创建或更新条目时,字段数据需以 字段 ID(而非字段名)为键:
const fields = await collection.getFields()
const titleField = fields.find(f => f.name === "Title")
await collection.addItems([{
slug: "my-article",
fieldData: {
[titleField.id]: { type: "string", value: "My Article Title" },
}
}])
支持的字段类型及其值格式:
| 类型 | 值格式 | 示例 |
|---|---|---|
string |
string |
{ type: "string", value: "Hello" } |
number |
number |
{ type: "number", value: 42 } |
boolean |
boolean |
{ type: "boolean", value: true } |
date |
string(UTC ISO 格式) |
{ type: "date", value: "2026-04-06T00:00:00Z" } |
formattedText |
string(HTML) |
{ type: "formattedText", value: " |
link |
string(URL) |
{ type: "link", value: "https://example.com" } |
image |
ImageAsset 对象 |
参见图片上传章节 |
enum |
string(枚举项名称) |
{ type: "enum", value: "Published" } |
color |
string(十六进制 / rgba) |
{ type: "color", value: "#FF0000" } |
file |
FileAsset 对象 |
行为类似 image 字段 |
collectionReference |
string(条目 ID) |
{ type: "collectionReference", value: "itemId123" } |
multiCollectionReference |
string[] |
{ type: "multiCollectionReference", value: ["id1","id2"] } |
图片
从公开 URL 上传图片,然后在 CMS 条目中引用返回的 asset:
const asset = await framer.uploadImage("https://example.com/photo.jpg")
// asset = { id, url, thumbnailUrl }
await item.setAttributes({
fieldData: {
[thumbnailField.id]: { type: "image", value: asset.url }
}
})
发布(Publishing)与部署(Deployment)
// 创建预览部署
const result = await framer.publish()
// result = { deployment: { id }, hostnames: [...] }
// 将预览部署提升为生产环境
await framer.deploy(result.deployment.id)
每次部署至生产环境前,务必向用户确认。 发布预览是安全操作;而部署将直接影响线上环境。
项目信息与变更
await framer.getProjectInfo() // { id, name, apiVersion1Id }
await framer.getCurrentUser() // { id, name, avatar }
await framer.getPublishInfo() // 当前部署状态
await framer.getChangedPaths() // { added, removed, modified }
await framer.getChangeContributors() // 贡献者 UUID 列表
await framer.getDeployments() // 全部部署历史
其他操作
| 操作 | 方法 | 说明 |
|---|---|---|
| 颜色样式 | getColorStyles(), createColorStyle() |
设计令牌(Design Tokens) |
| 文本样式 | getTextStyles(), createTextStyle() |
排版令牌(Typography Tokens) |
| 代码文件 | getCodeFiles(), createCodeFile(name, code) |
自定义代码覆盖 |
| 自定义代码 | getCustomCode() |
注入到 head / body 的代码 |
| 字体 | getFonts() |
项目所用字体 |
| 多语言区域设置(Locales) | getLocales(), getDefaultLocale() |
i18n 支持 |
| 页面 | createWebPage(path), removeNode(id) |
页面管理 |
| 截图 | screenshot(nodeId, options) |
任意节点的 PNG 缓冲区 |
| 重定向 | addRedirects([{from, to}]) |
需付费计划支持 |
| 节点树 | getNode(id), getChildren(id), getParent(id) |
DOM 遍历 |
常见工作流
向 CMS 推送一篇新文章
完整流程(含字段解析、图片上传及错误处理)请参见 references/cms-operations.md。
批量更新文章
const items = await collection.getItems()
for (const item of items) {
await item.setAttributes({
fieldData: {
[metaField.id]: { type: "string", value: generateMeta(item) }
}
})
}
CMS 更改后执行发布
const changes = await framer.getChangedPaths()
if (changes.added.length || changes.modified.length || changes.removed.length) {
const result = await framer.publish()
console.log("预览地址:", result.hostnames)
// 部署前请先向用户确认:await framer.deploy(result.deployment.id)
}
重要注意事项
- API 密钥作用域:每个密钥仅绑定一个项目。若需管理多个 Framer 站点,请分别存储多个密钥。
- WebSocket 连接:
connect()调用会建立持久化 WebSocket 连接。操作完成后务必调用disconnect();或使用using framer = await connect(...)实现自动清理。 - 使用字段 ID,而非字段名:CMS 操作均依赖字段 ID。务必先调用
getFields()并将字段名解析为对应 ID。 - 图片字段:需传入
uploadImage()返回的完整framerusercontent.comURL,而非 asset ID。 - 代理方法:多数方法(如 getCollections、publish 等)均为代理方法 —— 它们不会出现在
Object.keys(framer)中,但可正常调用。 - 速率限制:官方未明确文档化速率限制,但仍建议避免高频请求。对批量操作(如处理 100+ 条目)应加入小幅延迟。
formattedText字段:支持标准 HTML 标签(h1–h6、p、ul、ol、li、a、strong、em、img、blockquote、pre、code、table 等)。- 草稿条目:条目可设置
draft: true;草稿内容默认不参与发布。 - 博客文章集合(Blog Posts collection):由
"thisPlugin"管理的集合仅可通过 API 读取,不可修改;仅"user"管理的集合支持写入操作。
热门AI工具
相关专题
本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。
0
2026.10.22
本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。
0
2026.10.22
本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。
0
2026.10.22
本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。
0
2026.10.22
本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。
0
2026.10.22
本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。
0
2026.10.22
本专题讲解Golangci-lint的安装、初始化、基础命令和首次代码检查,覆盖本地环境、Docker及多平台用法,帮助Go开发者快速上手。
0
2026.10.22
PHP2Shell漏洞是什么,哪些PHP版本和运行环境会受到影响,服务器应该如何检测与修复?本专题提供版本自查脚本、Linux与Docker升级命令、PHP-FPM和Apache排查步骤,以及修复验证、临时缓解和应急响应方案。
0
2026.10.22
热门下载
相关下载
精品课程
共6课时 | 12.1万人学习
共79课时 | 161.5万人学习
共6课时 | 54.7万人学习
