Framer
Publish Serpon articles into a Framer CMS collection using the webhook and Framer's Server API.
Framer
Serpon has no native Framer connector, and the reason is worth understanding before you build around it: Framer has no REST API for writing CMS items. Its CMS is reachable two ways, and neither is a plain HTTP endpoint a third party can call on your behalf.
| Path | Runs where | Suitable for us |
|---|---|---|
| Plugin API | Inside the Framer editor | No — requires the editor open |
| Server API | Your own server, via the framer-api npm package | Yes, with a small service of your own |
The Server API is what makes this possible at all. It is currently in open beta, and it is a JavaScript package rather than an HTTP interface — so the bridge has to be a small piece of JavaScript you run.
Because Framer's write path is a Node package and not REST, no-code connectors that only speak HTTP — Zapier, Make — cannot write to the Framer CMS today. You need somewhere to execute JavaScript: self-hosted n8n, or a small service of your own.
How it fits together
Serpon ──webhook──▶ your bridge (Node + framer-api) ──▶ Framer CMS
Serpon posts the finished article to your bridge, the bridge writes a CMS item with the framer-api package, and optionally publishes the site.
1. Get a Framer API key
In your Framer project, open Site Settings → General and create an API key. You will also need the project URL, in the form https://framer.com/projects/<id>.
Store both as environment variables. The key grants write access to your site — treat it like a password and keep it server-side.
2. Point a Serpon webhook at your bridge
Create a Custom Webhook integration under Integrations with your bridge's URL. Set Payload content format to markdown or json depending on what your Framer fields expect.
See the webhook reference for the full payload. The fields you'll usually map:
| Serpon | Framer CMS field |
|---|---|
data.title | Title (text) |
content.markdown or content.html | Body (rich text / markdown) |
content.meta_title | SEO title (text) |
content.meta_description | SEO description (text) |
data.external_id | A hidden text field, as an idempotency key |
Serpon does not sign webhook payloads. Your bridge is a public endpoint that writes to your live site, so protect it — an unguessable URL at minimum, ideally a shared token you check before doing any work.
3. Write the bridge
Connect with the framer-api package and create the CMS item when a payload arrives:
import express from "express"
import { connect } from "framer-api"
const app = express()
app.use(express.json())
app.post("/serpon", async (req, res) => {
if (req.get("x-bridge-token") !== process.env.BRIDGE_TOKEN) {
return res.sendStatus(401)
}
const { data, content } = req.body
res.sendStatus(200) // acknowledge before the slow work
const framer = await connect(
process.env.FRAMER_PROJECT_URL,
process.env.FRAMER_API_KEY,
)
// Write the item into your collection, then publish. Consult the Framer
// Server API docs for the current collection methods and their arguments —
// the API is in beta and its surface is still moving.
await framer.publish()
await framer.disconnect()
})
app.listen(3000)
Deliberately left abstract: the exact collection-write call belongs to Framer's beta API, and pinning a signature here that changes next month would be worse than sending you to the source. Check the Server API quick start for the current methods.
Two things to get right regardless of the call shape:
Acknowledge fast. Serpon retries three times on a non-2xx and then records the publish as failed. Respond before connecting to Framer.
Deduplicate on data.external_id. A retry re-sends the same article. Store that ID on the item and skip anything you've already written, or a timeout after a successful write becomes a duplicate post.
Running it on n8n
If you self-host n8n, the bridge can be a workflow instead of a service: a Webhook node for the trigger, a Code node running the framer-api calls, and a Respond to Webhook node returning 200 immediately. The NODE_FUNCTION_ALLOW_EXTERNAL environment variable must include framer-api for the Code node to import it. n8n Cloud does not allow arbitrary npm imports, so this needs a self-hosted instance.
When this gets easier
Framer's Server API is in open beta. If it stabilizes — or Framer ships a REST surface for CMS writes — a native Serpon connector becomes possible, and this page gets replaced with a two-field setup screen like Webflow's. Until then, the bridge is the supported route.