📦 Framer CRM API — Framer CMS管理

v1.0.1

通过 Framer Server API 在本地一键完成 CMS 集合与项目的增删改查、图片上传、预览发布及线上部署,无需打开 Framer 后台。

1· 83·0 当前·0 累计
下载技能包
最后更新
2026/4/6
0
安全扫描
VirusTotal
无害
查看报告
OpenClaw
安全
medium confidence
该技能的需求与运行指令与其声明的“通过 Server API 管理 Framer CMS”目的一致;仅依赖 Node/npm 及 Framer 项目 URL + API 密钥,并指示标准初始化步骤,但技能来源未知且会在用户项目中安装包、读写 .env,请使用前审查。
评估建议
此技能看起来确为 Framer Server API 助手。安装或运行前请注意:1) 未提供技能来源/主页——在交付项目凭证前请确认发布者可信。2) 会要求输入 FRAMER_PROJECT_URL 与 FRAMER_API_KEY 并可能写入本地 .env;确保 .env 已加入 .gitignore,避免将密钥提交到版本库。3) 技能会执行 `npm i framer-api`——安装前请自行审查该 npm 包(维护者、下载量、源码)。4) 要求代理在执行影响大的操作(发布/部署、删除、批量处理)前必须征得你确认。5) 尽量创建作用域受限的 API 密钥用于自动化,并在停用技能后轮换或撤销密钥。如需更高保障,请向发布者索要来源信息(主页、仓库链接),或优先选用可审计源码的技能。...
详细分析 ▾
用途与能力
名称/描述、所需二进制文件(node、npm)及所需环境变量(FRAMER_PROJECT_URL、FRAMER_API_KEY)均与声明的“通过 Framer Server API 管理 CMS”目的相符;要求安装 `framer-api` npm 包属预期行为。
指令范围
SKILL.md 指示代理读取用户环境或 .env 文件,并在初始化时将凭证追加至项目 .env 并执行 npm install/init。这些操作对 CMS 自动化技能属合理范围,但涉及读取与写入凭证文件以及在用户项目中安装包——用户应确认这些操作并安全处理密钥。技能明确提示部署前需确认,这是良好实践。
安装机制
此为纯指令技能(无安装规范)。唯一描述的安装操作是在项目中运行 `npm i framer-api`,该操作标准且可追踪至 npm;技能指令中未出现任意下载或从 URL 解压步骤。
凭证需求
唯一所需环境变量为 FRAMER_PROJECT_URL 与 FRAMER_API_KEY(主要凭证),与连接 Framer 项目的技能需求相称。初始化流程也适当建议将密钥存入 .env 并检查 .gitignore。
持久化与权限
技能标志显示无强制持久化(always: false)且采用普通自主调用设置。运行时指令仅写入项目 .env 并可选择安装一个包;未请求系统级配置或修改其他技能。
安全有层次,运行前请审查代码。

运行时依赖

无特殊依赖

版本

latestv1.0.12026/4/6

**针对 CMS 字段更新的关键修正与说明。** - 更新文档以阐明:使用 `item.setAttributes` 更新 CMS 项目字段时,所有字段值必须包裹在 `fieldData` 对象内;未包裹将导致更新被静默忽略。 - 添加了正确与错误使用 `setAttributes` 的清晰示例。 - 阐明非字段属性(如 slug、draft)必须直接设置,而非放在 fieldData 内。 - 对更新/创建 CMS 项目工作流进行小幅准确性调整。 - 仅涉及文档与使用指导,无代码变更。

无害

安装命令

点击复制
官方npx clawhub@latest install framer-crm-api
镜像加速npx clawhub@latest install framer-crm-api --registry https://cn.longxiaskill.com

技能文档

通过 framer-api npm 包,以编程方式管理 Framer CMS 内容。无需打开 Framer 应用,即可在终端推送文章、上传图片、创建集合、发布/部署。

首次设置(引导)

如果用户首次在项目中使用该技能,请运行 references/onboarding.md 中描述的引导流程。 快速检查: 在用户的 .env 文件或环境中查找 FRAMER_PROJECT_URLFRAMER_API_KEY。若缺失,则进行引导。


工作原理

本技能使用 Framer Server APIframer-api npm 包),通过 API Key 以 WebSocket 方式连接 Framer 项目,提供完整的 CMS CRUD、图片上传、发布与部署功能。

重要: 项目中必须已安装 framer-api。如未安装,请运行:

npm i framer-api

所有操作均采用 ES module 脚本.mjs 文件),连接模式如下:

import { connect } from "framer-api"
// 重要:API key 作为普通字符串传入(第 2 参数),而非 {apiKey: "..."}
const framer = await connect(process.env.FRAMER_PROJECT_URL, process.env.FRAMER_API_KEY)
try {
  // ... 操作 ...
} finally {
  await framer.disconnect()
}

可用操作

CMS 集合

操作方法说明
列出集合framer.getCollections()返回所有 CMS 集合
获取单个集合framer.getCollection(id)通过集合 ID
创建集合framer.createCollection(name)创建空集合
获取字段collection.getFields()字段定义(名称、类型、ID)
添加字段collection.addFields([{type, name}])向集合添加新字段
删除字段collection.removeFields([fieldId])按 ID 删除字段
排序字段collection.setFieldOrder([fieldIds])设置字段显示顺序

CMS 条目(文章、记录)

操作方法说明
列出条目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"
    }
  }
}])

支持的字段类型及其值格式:

类型值格式示例
stringstring{ type: "string", value: "Hello" }
numbernumber{ type: "number", value: 42 }
booleanboolean{ type: "boolean", value: true }
datestring(UTC ISO){ type: "date", value: "2026-04-06T00:00:00Z" }
formattedTextstring(HTML){ type: "formattedText", value: "

Title

Text

" }
linkstring(URL){ type: "link", value: "https://example.com" }
imageImageAsset 对象见图片上传章节
enumstring(枚举名){ type: "enum", value: "Published" }
colorstring(hex/rgba){ type: "color", value: "#FF0000" }
fileFileAsset 对象与 image 类似
collectionReferencestring(条目 ID){ type: "collectionReference", value: "itemId123" }
multiCollectionReferencestring[]{ type: "multiCollectionReference", value: ["id1","id2"] }

图片

从公开 URL 上传图片,然后将返回的 asset 用于 CMS 条目:

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
    }
  }
})

发布与部署

// 创建预览部署
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()设计令牌
文本样式getTextStyles(), createTextStyle()排版令牌
代码文件getCodeFiles(), createCodeFile(name, code)自定义代码覆盖
自定义代码getCustomCode()头部/主体代码注入
字体getFonts()项目字体
本地化getLocales(), getDefaultLocale()国际化
页面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("Preview:", result.hostnames)
  // 询问用户后再:
  // await framer.deploy(result.deployment.id)
}

重要提示

  • API key 作用域: 每个 key 仅绑定一个项目。多个 Framer 站点需存储多个 key。
  • WebSocket 连接: connect() 会建立持久 WebSocket。完成后务必 disconnect(),或使用 using framer = await connect(...) 自动清理。
  • 使用字段 ID,而非名称: CMS 操作均使用字段 ID。务必先 getFields() 并将名称解析为 ID。
  • 图片字段: 传入 uploadImage() 返回的完整 framerusercontent.com URL,而非 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 集合:"thisPlugin" 管理的集合通过 API 只读。仅 "user" 管理的集合可修改。
数据来源ClawHub ↗ · 中文优化:龙虾技能库