From webflow-pack
Generates TypeScript examples for Webflow Data API v2: list sites, read CMS collections/items, create items. For new integrations, testing setups, or learning basics.
How this skill is triggered — by the user, by Claude, or both
Slash command
/webflow-pack:webflow-hello-worldThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Minimal working examples demonstrating the three core Webflow Data API v2 operations:
Minimal working examples demonstrating the three core Webflow Data API v2 operations: listing sites, reading CMS collections/items, and creating a CMS item.
webflow-install-auth setupwebflow-api package installedsites:read and cms:read scopesEvery Webflow API call starts with a site_id. List your sites to find it:
// hello-webflow.ts
import { WebflowClient } from "webflow-api";
const webflow = new WebflowClient({
accessToken: process.env.WEBFLOW_API_TOKEN!,
});
async function listSites() {
const { sites } = await webflow.sites.list();
for (const site of sites!) {
console.log(`${site.displayName}`);
console.log(` ID: ${site.id}`);
console.log(` Short name: ${site.shortName}`);
console.log(` Custom domains: ${site.customDomains?.map(d => d.url).join(", ")}`);
console.log(` Last published: ${site.lastPublished}`);
console.log(` Locales: ${site.locales?.map(l => l.displayName).join(", ")}`);
}
}
listSites().catch(console.error);
Collections define your content types (blog posts, team members, products, etc.):
async function listCollections(siteId: string) {
const { collections } = await webflow.collections.list(siteId);
for (const col of collections!) {
console.log(`Collection: ${col.displayName}`);
console.log(` ID: ${col.id}`);
console.log(` Slug: ${col.slug}`);
console.log(` Item count: ${col.itemCount}`);
console.log(` Fields:`);
for (const field of col.fields || []) {
console.log(` - ${field.displayName} (${field.type}, required: ${field.isRequired})`);
}
}
}
// Usage: pass your site_id
listCollections("your-site-id").catch(console.error);
Fetch items from a collection — staged (draft) or live (published):
async function readItems(collectionId: string) {
// Get staged (draft + published) items
const { items } = await webflow.collections.items.listItems(collectionId, {
limit: 10,
offset: 0,
});
for (const item of items!) {
console.log(`Item: ${item.fieldData?.name || item.id}`);
console.log(` ID: ${item.id}`);
console.log(` Slug: ${item.fieldData?.slug}`);
console.log(` Draft: ${item.isDraft}`);
console.log(` Archived: ${item.isArchived}`);
console.log(` Created: ${item.createdOn}`);
}
// Get live (published) items only
const live = await webflow.collections.items.listItemsLive(collectionId, {
limit: 10,
});
console.log(`\nLive items: ${live.items?.length}`);
}
async function createBlogPost(collectionId: string) {
// Items are created as drafts by default (isDraft: true)
const item = await webflow.collections.items.createItem(collectionId, {
fieldData: {
name: "Hello from the API",
slug: "hello-from-api",
// Field names must match your collection schema
// Use the slug version of field names (lowercase, hyphens)
"post-body": "<p>This post was created via the Webflow Data API v2.</p>",
"author": "API Bot",
"published-date": new Date().toISOString(),
},
isDraft: false, // Set false to stage for publishing
});
console.log(`Created item: ${item.id}`);
console.log(` Draft: ${item.isDraft}`);
console.log(` Slug: ${item.fieldData?.slug}`);
return item;
}
import { WebflowClient } from "webflow-api";
const webflow = new WebflowClient({
accessToken: process.env.WEBFLOW_API_TOKEN!,
});
async function main() {
// 1. Get first site
const { sites } = await webflow.sites.list();
const site = sites![0];
console.log(`Using site: ${site.displayName} (${site.id})\n`);
// 2. List collections
const { collections } = await webflow.collections.list(site.id!);
console.log(`Found ${collections!.length} collections:`);
for (const col of collections!) {
console.log(` - ${col.displayName} (${col.itemCount} items)`);
}
// 3. Read items from first collection
if (collections!.length > 0) {
const firstCol = collections![0];
const { items } = await webflow.collections.items.listItems(firstCol.id!, {
limit: 5,
});
console.log(`\nFirst ${items!.length} items in "${firstCol.displayName}":`);
for (const item of items!) {
console.log(` - ${item.fieldData?.name} (${item.id})`);
}
}
console.log("\nWebflow connection verified successfully.");
}
main().catch(console.error);
Run it:
npx tsx hello-webflow.ts
Webflow connection verified successfully.| Error | Cause | Solution |
|---|---|---|
401 Unauthorized | Bad token | Re-check token at developers.webflow.com |
403 Forbidden | Missing cms:read scope | Add scope to token or app |
404 Not Found | Wrong site_id or collection_id | List sites first to get valid IDs |
429 Too Many Requests | Rate limited | Wait 60s (Retry-After header) |
Empty sites array | Token has no site access | Check workspace token permissions |
sites.list().collections.list(siteId).post-body, not Post Body).isDraft: true. Set false to stage for publishing.listItems() returns all items; listItemsLive() returns only published.Proceed to webflow-local-dev-loop for development workflow setup.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin webflow-packManages Webflow CMS content via Data API v2: list collections, CRUD items, publish, and manage content lifecycle. Use for blog posts, team members, or any dynamic content.
Automates Webflow CMS collection CRUD, site publishing, page inspection, asset uploads, and ecommerce order retrieval via Composio's Webflow toolkit through Rube MCP.
Automates Webflow CMS collections, site publishing, page management, asset uploads, and ecommerce orders via Composio's Webflow toolkit and Rube MCP.