agentsclimarketplace

Publish webflow

Skill busyeugene/content-marketing-skills/publish-webflow

Claude Code Skills for content marketers — briefs, drafts, SEO audits, competitor analysis, publishing

Install
npx -y skills add busyeugene/content-marketing-skills --skill publish-webflow

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

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 declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.1 KB, as published. Nobody here has run it

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. Modedraft (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 updatePATCH /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).

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.