agentleFS
busyeugenebusyeugene/content-marketing-skills/publish-webflow/SKILL.md

publish-webflow

Skill1 starsChanged 7 months agoMITView on GitHub

Use when the user wants to publish a blog post draft to Webflow CMS via the Webflow API v2. Reads a markdown draft, maps frontmatter to CMS fields, creates or updates the CMS item, and optionally publishes it live.

The file

Show its rules and text

We split this skill into the rules it gives an agent

19 rules. About 0 are common, 7 are distinctive, and 12 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈7

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 12

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use AskUserQuestion for mode and existing-item handling.

    line 37
  2. Very specific:

    Call GET /v2/collections/{WEBFLOW_COLLECTION_ID} and cache the field list.

    line 43
  3. Distinctive:

    If the user provides a custom mapping file, it overrides the defaults.

    line 61
  4. Distinctive:

    Read the draft file.

    line 65
  5. Very specific:

    If hero_image is a local path, upload via the Webflow 2-step asset flow:

    line 69
  6. Distinctive:

    If it's already a URL, use it directly.

    line 72
  7. Very specific:

    If found and mode is skip → stop and report.

    line 79
  8. Very specific:

    If found and mode is update → PATCH /v2/collections/{collection_id}/items/{item_id} with the new field values.

    line 80
  9. Very specific:

    If found and mode is create-new → append a timestamp to the slug, then create.

    line 81
  10. Distinctive:

    If not found → create.

    line 82
  11. Very specific:

    Create live (mode = live, single call): use POST /v2/collections/{collection_id}/items/live with the same body and isDraft: false.

    line 98
  12. Very specific:

    New item: use the POST /v2/collections/{collection_id}/items/live create-live endpoint above in step 4 instead of the staged create.

    line 114
  13. Very specific:

    Ask via AskUserQuestion the first time a publish runs in a session.

    line 128
  14. Very specific:

    If SLACK_WEBHOOK_URL is set and publish was successful:

    line 132
  15. Distinctive:

    Image upload fails: ask the user to upload manually via Webflow and retry.

    line 157
  16. Distinctive:

    Site publish rate limited: create/update the item anyway, skip the site publish, and note it in the log so the user can publish manually …

    line 158
  17. Very specific:

    Default mode is draft. This skill never publishes live without explicit user confirmation in the current session.

    line 162
  18. Very specific:

    Never delete existing items.

    line 163
  19. Distinctive:

    If mode = live, the public URL returns 200.

    line 169

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Publish → Webflow

Publish a local markdown draft to Webflow CMS using the Webflow Data API v2.

Setup

Required:

  • WEBFLOW_API_TOKEN — a Data API token (Site Settings → Apps & Integrations → API Access). Scopes needed: cms:read, cms:write, sites:read, and (if publishing live) sites:write.
  • WEBFLOW_SITE_ID — the site ID. Get it via GET https://api.webflow.com/v2/sites.
  • WEBFLOW_COLLECTION_ID — the collection ID for your blog. Get it via GET /v2/sites/{site_id}/collections.

Optional:

  • SLACK_WEBHOOK_URL — Slack notification when a post goes live.

All requests use:

Authorization: Bearer ${WEBFLOW_API_TOKEN}
accept-version: 2.0.0
Content-Type: application/json

Inputs

  1. Draft path — markdown file under posts/.
  2. Mode — draft (create as unpublished) or live (create and publish). Default draft.
  3. Update existing? — if an item with the same slug exists, skip, update, or create-new. Default update.
  4. Field mapping override — optional: path to a JSON file mapping markdown frontmatter keys to Webflow field slugs. Default mapping is documented below.

Use AskUserQuestion for mode and existing-item handling.

Process

1. Validate collection schema

Call GET /v2/collections/{WEBFLOW_COLLECTION_ID} and cache the field list. For each required frontmatter field, confirm there's a matching Webflow field. If a field is missing, fail fast with a clear error naming which Webflow field to add.

Default frontmatter → Webflow field mapping:

Frontmatter keyWebflow field slugType
titlenamePlainText
slugslugPlainText
meta_titlemeta-titlePlainText
meta_descriptionmeta-descriptionPlainText
authorauthorReference (fallback PlainText)
datepublished-onDate
hero_imagehero-imageImage
hero_althero-altPlainText
keywordprimary-keywordPlainText
status—(ignored; controlled by publish mode)
bodypost-bodyRichText

If the user provides a custom mapping file, it overrides the defaults.

2. Load and transform the draft

  • Read the draft file.
  • Parse frontmatter.
  • Convert the markdown body to Webflow-compatible HTML (rich text field accepts HTML). Preserve: headings, paragraphs, lists, code blocks, blockquotes, images, internal and external links. Strip any HTML comments.
  • For the hero image:
    • If hero_image is a local path, upload via the Webflow 2-step asset flow:
      1. POST /v2/sites/{site_id}/assets with { "fileName": "...", "fileHash": "<md5>" }. Response contains uploadUrl and uploadDetails (S3 presigned fields).
      2. POST the file as multipart/form-data to uploadUrl, including every field from uploadDetails before the file field. Use the returned asset hostedUrl in fieldData.
    • If it's already a URL, use it directly.
  • For author as a reference field: resolve the name to an author collection item ID via GET /v2/collections/{authors_collection}/items?name={author}. If not found, create the author item (or fall back to PlainText if the field allows).

3. Check for existing item

GET /v2/collections/{WEBFLOW_COLLECTION_ID}/items?slug={slug}

  • If found and mode is skip → stop and report.
  • If found and mode is update → PATCH /v2/collections/{collection_id}/items/{item_id} with the new field values.
  • If found and mode is create-new → append a timestamp to the slug, then create.
  • If not found → create.

4. Create or update

Create (staged / draft):

POST /v2/collections/{WEBFLOW_COLLECTION_ID}/items
{
  "isArchived": false,
  "isDraft": <true if mode=draft else false>,
  "fieldData": { ...mapped fields }
}

For bulk creates (multiple posts at once), use POST /v2/collections/{collection_id}/items/bulk with { "items": [...] }. As of Dec 2024 newly-created items default to isDraft: true unless the live endpoint is used.

Create live (mode = live, single call): use POST /v2/collections/{collection_id}/items/live with the same body and isDraft: false. This creates and publishes in one shot.

Update:

PATCH /v2/collections/{WEBFLOW_COLLECTION_ID}/items/{item_id}
{
  "fieldData": { ...mapped fields }
}

Handle the response: capture id (item ID), lastUpdated, and the fieldData.slug.

5. Publish live (if mode = live)

There is no per-item "promote to live" endpoint in the Data API v2. Options:

  • New item: use the POST /v2/collections/{collection_id}/items/live create-live endpoint above in step 4 instead of the staged create.
  • Existing staged item: PATCH the item with isDraft: false via PATCH /v2/collections/{collection_id}/items/{item_id}/live (the /live bulk-publish path accepts an item list) — or publish the entire site, which flushes all staged items.

Then publish the site so any staged changes are visible:

POST /v2/sites/{WEBFLOW_SITE_ID}/publish
{ "publishToWebflowSubdomain": false, "customDomains": [...] }

Or if the user only wants the staging subdomain:

{ "publishToWebflowSubdomain": true }

Ask via AskUserQuestion the first time a publish runs in a session.

6. Optional Slack notification

If SLACK_WEBHOOK_URL is set and publish was successful:

POST ${SLACK_WEBHOOK_URL}
Content-Type: application/json

{ "text": "📤 New post published: <{live URL}|{title}>" }

7. Write a publish log

Append a line to publish-log.md at the project root:

| {YYYY-MM-DD HH:mm} | webflow | {mode} | {title} | {item_id} | {live URL or "—"} | {status} |

8. Print summary

One block: mode, item ID, live URL (if live), Slack notified (Y/N), publish-log updated.

Fallbacks

  • Missing required env var: fail fast with the exact variable name.
  • Collection schema mismatch: print the missing field names and the expected types; do not guess.
  • Image upload fails: ask the user to upload manually via Webflow and retry; don't create the item without the hero if the field is required.
  • Site publish rate limited: create/update the item anyway, skip the site publish, and note it in the log so the user can publish manually from the Webflow dashboard.

Safety

  • Default mode is draft. This skill never publishes live without explicit user confirmation in the current session.
  • Never delete existing items. If a collision happens in skip mode, stop and report.

Verification

  1. Item exists in the target collection (GET /items/{id} returns 200).
  2. fieldData contains all mapped fields with expected values.
  3. If mode = live, the public URL returns 200.
  4. publish-log.md has a new row.
  5. Slack notification delivered (if configured).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.