← 返回 Skills 市场
berthelol

Framer CRM API

作者 berthelol · GitHub ↗ · v1.0.1 · MIT-0
cross-platform ✓ 安全检测通过
124
总下载
1
收藏
0
当前安装
2
版本数
在 OpenClaw 中安装
/install framer-crm-api
功能描述
Framer CMS management via the Server API — list, create, read, update, and delete CMS collections and items, upload images, publish previews, deploy to produ...
使用说明 (SKILL.md)

Framer CMS — Server API Skill

Manage Framer CMS content programmatically via the framer-api npm package. Push articles, upload images, create collections, and publish/deploy — all from the terminal, no Framer app needed.

First-time setup (onboarding)

If this is the first time the user uses this skill in a project, run the onboarding flow described in references/onboarding.md.

Quick check: Look for FRAMER_PROJECT_URL and FRAMER_API_KEY in the user's .env file or environment. If missing, onboard.


How it works

This skill uses the Framer Server API (framer-api npm package) which connects to Framer projects via WebSocket using an API key. It provides full CMS CRUD, image uploads, publishing, and deployment.

Important: The framer-api package must be installed in the project. If not present, run:

npm i framer-api

All operations use ES module scripts (.mjs files) with this connection pattern:

import { connect } from "framer-api"

// IMPORTANT: API key is passed as a plain string (2nd argument), NOT as {apiKey: "..."}
const framer = await connect(process.env.FRAMER_PROJECT_URL, process.env.FRAMER_API_KEY)
try {
  // ... operations ...
} finally {
  await framer.disconnect()
}

Available operations

CMS Collections

Operation Method Notes
List collections framer.getCollections() Returns all CMS collections
Get one collection framer.getCollection(id) By collection ID
Create collection framer.createCollection(name) Creates empty collection
Get fields collection.getFields() Field definitions (name, type, id)
Add fields collection.addFields([{type, name}]) Add new fields to collection
Remove fields collection.removeFields([fieldId]) Delete fields by ID
Reorder fields collection.setFieldOrder([fieldIds]) Set field display order

CMS Items (articles, entries)

Operation Method Notes
List items collection.getItems() All items with field data
Create items collection.addItems([{slug, fieldData}]) Create new items. Returns undefined — re-fetch with getItems() to get IDs
Update item fields item.setAttributes({ fieldData: { [fieldId]: {type, value} } }) MUST wrap in fieldData: — without it, values are silently ignored
Update item slug/draft item.setAttributes({ slug: "new", draft: false }) Slug and draft are set directly (NOT inside fieldData)
Delete item item.remove() Single item
Bulk delete collection.removeItems([itemIds]) Multiple items
Reorder items collection.setItemOrder([itemIds]) Set display order

⚠️ Critical: How to update CMS item fields

The setAttributes method has a non-obvious API design — field values MUST be wrapped in a fieldData key:

// ✅ CORRECT — fields wrapped in fieldData
await item.setAttributes({
  fieldData: {
    [titleFieldId]: { type: "string", value: "New Title" }
  }
})

// ❌ WRONG — silently ignored, no error thrown
await item.setAttributes({
  [titleFieldId]: { type: "string", value: "New Title" }
})

// ❌ WRONG — also silently ignored
await item.setAttributes({
  [titleFieldId]: "New Title"
})

Partial updates work: Only specified fields are changed. Other fields are preserved.

Non-field attributes (slug, draft) go directly on the object, NOT inside fieldData:

await item.setAttributes({ slug: "new-slug", draft: false })

Field data format

When creating/updating items, field data is keyed by field ID (not name):

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" },
  }
}])

Supported field types and their value format:

Type Value format Example
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: "\x3Ch2>Title\x3C/h2>\x3Cp>Text\x3C/p>" }
link string (URL) { type: "link", value: "https://example.com" }
image ImageAsset object See image upload section
enum string (case name) { type: "enum", value: "Published" }
color string (hex/rgba) { type: "color", value: "#FF0000" }
file FileAsset object Similar to image
collectionReference string (item ID) { type: "collectionReference", value: "itemId123" }
multiCollectionReference string[] { type: "multiCollectionReference", value: ["id1","id2"] }

Images

Upload images from public URLs, then use the returned asset in CMS items:

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

// Create a preview deployment
const result = await framer.publish()
// result = { deployment: { id }, hostnames: [...] }

// Promote preview to production
await framer.deploy(result.deployment.id)

Always ask the user before deploying to production. Publishing a preview is safe; deploying is live.

Project info & changes

await framer.getProjectInfo()       // { id, name, apiVersion1Id }
await framer.getCurrentUser()       // { id, name, avatar }
await framer.getPublishInfo()       // Current deployment status
await framer.getChangedPaths()      // { added, removed, modified }
await framer.getChangeContributors() // Contributor UUIDs
await framer.getDeployments()       // All deployment history

Other operations

Operation Method Notes
Color styles getColorStyles(), createColorStyle() Design tokens
Text styles getTextStyles(), createTextStyle() Typography tokens
Code files getCodeFiles(), createCodeFile(name, code) Custom code overrides
Custom code getCustomCode() Head/body code injection
Fonts getFonts() Project fonts
Locales getLocales(), getDefaultLocale() i18n
Pages createWebPage(path), removeNode(id) Page management
Screenshots screenshot(nodeId, options) PNG buffer of any node
Redirects addRedirects([{from, to}]) Requires paid plan
Node tree getNode(id), getChildren(id), getParent(id) DOM traversal

Common workflows

Push a new article to CMS

See references/cms-operations.md for the full pattern including field resolution, image upload, and error handling.

Bulk update articles

const items = await collection.getItems()
for (const item of items) {
  await item.setAttributes({
    fieldData: {
      [metaField.id]: { type: "string", value: generateMeta(item) }
    }
  })
}

Publish after CMS changes

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)
  // Ask user before: await framer.deploy(result.deployment.id)
}

Important notes

  • API key scope: Each key is bound to one project. For multiple Framer sites, store multiple keys.
  • WebSocket connection: The connect() call opens a persistent WebSocket. Always call disconnect() when done, or use using framer = await connect(...) for auto-cleanup.
  • Field IDs, not names: CMS operations use field IDs. Always call getFields() first and resolve names to IDs.
  • Image fields: Pass the full framerusercontent.com URL from uploadImage(), not the asset ID.
  • Proxy methods: Most methods (getCollections, publish, etc.) are proxied — they don't appear in Object.keys(framer) but work correctly.
  • Rate limits: No documented rate limits, but avoid hammering. Add small delays for bulk operations (100+ items).
  • formattedText fields: Accept standard HTML (h1-h6, p, ul, ol, li, a, strong, em, img, blockquote, pre, code, table, etc.).
  • Draft items: Items can have draft: true — drafts are excluded from publishing.
  • Blog Posts collection: Collections managed by "thisPlugin" are read-only via the API. Only "user" managed collections can be modified.
安全使用建议
This skill appears to be what it says: a Framer Server API helper. Before installing or running it, consider the following: 1) The skill's source/homepage is not provided — verify you trust the publisher before giving it access to project credentials. 2) It will ask you for FRAMER_PROJECT_URL and FRAMER_API_KEY and may write them into the local project's .env; ensure .env is in .gitignore and avoid committing secrets to version control. 3) The skill instructs running 'npm i framer-api' — review the 'framer-api' npm package (maintainer, downloads, code) yourself before installing. 4) Require the agent to prompt you for confirmation before performing impactful actions (publish/deploy, deletes, bulk operations). 5) Where possible create an API key with limited scope for automation and rotate/revoke keys if you stop using the skill. If you want higher assurance, ask the publisher for provenance (homepage, repo link) or prefer a skill whose source code you can audit.
功能分析
Type: OpenClaw Skill Name: framer-crm-api Version: 1.0.1 The skill provides a legitimate and well-documented interface for managing Framer CMS content and site deployment via the official `framer-api` npm package. It includes a structured onboarding flow in `references/onboarding.md` that handles sensitive credentials (`FRAMER_API_KEY`) responsibly by instructing the agent to store them in a `.env` file and ensuring that file is added to `.gitignore`. The instructions in `SKILL.md` and the reference files are consistent with the stated purpose and include safety checks, such as requiring user confirmation before production deployments.
能力评估
Purpose & Capability
Name/description, required binaries (node, npm), and required env vars (FRAMER_PROJECT_URL, FRAMER_API_KEY) align with the stated Framer Server API CMS management purpose. Asking to install the 'framer-api' npm package is expected.
Instruction Scope
SKILL.md instructs the agent to read the user's environment or .env file and, during onboarding, to append credentials to the project's .env and run npm install/init. These actions are within scope for a CMS automation skill, but they involve reading and writing a credentials file and installing packages in the user's project — the user should confirm these operations and ensure secrets are handled safely. The skill explicitly warns to confirm before deploy, which is good.
Install Mechanism
This is an instruction-only skill (no install spec). The only install action described is running 'npm i framer-api' in the project, which is standard and traceable to npm. No arbitrary downloads or extract-from-URL steps are present in the skill instructions.
Credentials
The only required environment variables are FRAMER_PROJECT_URL and FRAMER_API_KEY (the primary credential). These are proportional to a skill that connects to a Framer project. The onboarding flow also appropriately recommends storing keys in .env and checking .gitignore.
Persistence & Privilege
Skill flags show no forced persistence (always: false) and normal autonomous invocation settings. The skill's runtime instructions write only to the project's .env and optionally install a package; it does not request system-wide configuration or modify other skills.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install framer-crm-api
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /framer-crm-api 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.1
**Critical corrections and clarification for CMS field updates.** - Updated documentation to clarify that when using `item.setAttributes` to update CMS item fields, all field values must be wrapped in a `fieldData` object. Not wrapping causes updates to be silently ignored. - Added clear examples of correct and incorrect usage of `setAttributes`. - Clarified that non-field properties (like slug, draft) must be set directly, not inside `fieldData`. - Minor adjustments for accuracy in update/create CMS item workflows. - No code changes; documentation and usage guidance only.
v1.0.0
Initial release of framer-cms skill for managing Framer CMS content and deployments via the Server API. - Supports listing, creating, reading, updating, and deleting CMS collections and items. - Enables image uploads, site preview publishing, production deployment, and project asset management — all without opening Framer. - Onboards users automatically if Framer API credentials are missing. - Designed to automate Framer CMS workflows such as pushing articles, syncing content, and managing collections programmatically. - Clearly distinguishes from Framer design/animation tasks; strictly focused on CMS/content API automation.
元数据
Slug framer-crm-api
版本 1.0.1
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 2
常见问题

Framer CRM API 是什么?

Framer CMS management via the Server API — list, create, read, update, and delete CMS collections and items, upload images, publish previews, deploy to produ... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 124 次。

如何安装 Framer CRM API?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install framer-crm-api」即可一键安装,无需额外配置。

Framer CRM API 是免费的吗?

是的,Framer CRM API 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Framer CRM API 支持哪些平台?

Framer CRM API 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Framer CRM API?

由 berthelol(@berthelol)开发并维护,当前版本 v1.0.1。

💬 留言讨论