PublishingFramer

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.

PathRuns whereSuitable for us
Plugin APIInside the Framer editorNo — requires the editor open
Server APIYour own server, via the framer-api npm packageYes, 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:

SerponFramer CMS field
data.titleTitle (text)
content.markdown or content.htmlBody (rich text / markdown)
content.meta_titleSEO title (text)
content.meta_descriptionSEO description (text)
data.external_idA 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.

Was this page helpful?