Publish webflow
Claude Code Skills for content marketers — briefs, drafts, SEO audits, competitor analysis, publishing
npx -y skills add busyeugene/content-marketing-skills --skill publish-webflowAssembled 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 viaGET https://api.webflow.com/v2/sites.WEBFLOW_COLLECTION_ID— the collection ID for your blog. Get it viaGET /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
- Draft path — markdown file under
posts/. - Mode —
draft(create as unpublished) orlive(create and publish). Defaultdraft. - Update existing? — if an item with the same slug exists,
skip,update, orcreate-new. Defaultupdate. - 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 key | Webflow field slug | Type |
|---|---|---|
title | name | PlainText |
slug | slug | PlainText |
meta_title | meta-title | PlainText |
meta_description | meta-description | PlainText |
author | author | Reference (fallback PlainText) |
date | published-on | Date |
hero_image | hero-image | Image |
hero_alt | hero-alt | PlainText |
keyword | primary-keyword | PlainText |
status | — | (ignored; controlled by publish mode) |
| body | post-body | RichText |
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_imageis a local path, upload via the Webflow 2-step asset flow:POST /v2/sites/{site_id}/assetswith{ "fileName": "...", "fileHash": "<md5>" }. Response containsuploadUrlanduploadDetails(S3 presigned fields).- POST the file as multipart/form-data to
uploadUrl, including every field fromuploadDetailsbefore thefilefield. Use the returned assethostedUrlinfieldData.
- If it's already a URL, use it directly.
- If
- 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/livecreate-live endpoint above in step 4 instead of the staged create. - Existing staged item: PATCH the item with
isDraft: falseviaPATCH /v2/collections/{collection_id}/items/{item_id}/live(the/livebulk-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
skipmode, stop and report.
Verification
- Item exists in the target collection (
GET /items/{id}returns 200). fieldDatacontains all mapped fields with expected values.- If mode = live, the public URL returns 200.
publish-log.mdhas a new row.- Slack notification delivered (if configured).