update: I went and made a tool to help generate typescript types from your webflow CMS schema. It is open source and found here: GitHub - pat-mw/webflow-schemas: Experimental: Generating dynamic schemas from webflow Data API for a better DX
Needs work but is a start, and may be useful for some of you
—-
Hey all,
Coming here to propose a neat (and somewhat necessary) addition to the Data API which, in my opinion, would elevate the Developer Experience for everyone using the API to meet modern standards.
TLDR: The webflow-cli should be extended to include functionality for generating dynamic type schemas from Webflow collections / Ecommerce integration / Form Submissions etc.
The output could be as simple as a JSON file that includes types across the whole Webflow stack, or could be extended to output types defined in TypeScript (via TS types or Zod) and Python (via Pydantic).
The benefit is immediate, full typesafety when working with the Data API not just to the extent of the static API routes, but for the dynamic ones too. This tightens the development loop when working with the API by allowing Webflow to be the central source of truth for types.
Background:
In my case, I have a site foo-bar.com
hosted on Webflow. In this site, there are CMS collections like: ‘Artists’ and ‘Events’.
I have a second application app.foo-bar.com
which is a dynamic React application with features for two types of users: artists and admins.
There are a bunch of features unrelated to Webflow, but where Webflow comes in is the following few examples:
-
Artists logged into
app.foo-bar.com
can change their user profile, the data of which is stored primarily in Supabase and includes a bunch of fields which are only needed within the context of the app.I then trigger a hook anytime they update their profile so that I can sync a partial set of this data with the Webflow CMS for their public profile on
foo-bar.com
: which is a Webflow page that embeds their name, images, bio, links, etc. -
Admins logged into
app.foo-bar.com
can create, edit, and delete ‘Events’ - which are primarily stored in Supabase and include a bunch of hidden fields. Like the above example, I need to sync part of this data to my ‘Events’ collection on Webflow for the purpose of marketing and ticket sales.
What is the problem?
Fundamentally, there isn’t a ‘problem’ per se - Webflow’s APIs are increasingly robust and, once set up correctly, can allow all sorts of dynamic interactivity that goes way beyond my examples above.
However, the key part of that is that it plays nice once it’s set up correctly.
During development, however, the experience can be somewhat painful and lags behind my expectations set by modern development ecosystems.
To ensure the API calls (e.g., updating a collection item) contain all the relevant required fields of the correct types, developers often have to switch back and forth between their code, the API documentation, and the Webflow CMS editor—making multiple API calls to the /collections
endpoints just to retrieve schemas manually and compare request payloads with expected types manually.
The solution?
A relatively simple CLI script could significantly improve this Developer Experience (DX), and it wouldn’t even require extending the core API—just a change in how we interact with dynamic schemas.
Goal
The goal is to generate a single reference file that contains all the dynamic types defined by our CMS collections. This allows us to use them reliably in our applications and validate them before making API calls, directly inside our code editor of choice.
Proposed CLI Workflow
To generate this schema file whenever types need syncing, the process would be:
-
Fetch All Collections
- Call the
list collections
endpoint to retrieve all dynamic collections. - Response:
{ "collections": [ { "id": "63692ab61fb2852f582ba8f5", "displayName": "Products", "singularName": "Product", "slug": "product" }, { "id": "63692ab61fb2856e6a2ba8f6", "displayName": "Categories", "singularName": "Category", "slug": "category" } ] }
- Call the
-
Fetch Collection Schema for Each Collection
- Call the
get collection details
endpoint for each collection. - Example response:
{ "id": "580e63fc8c9a982ac9b8b745", "displayName": "Blog Posts", "fields": [ { "id": "23cc2d952d4e4631ffd4345d2743db4e", "isRequired": true, "type": "PlainText", "displayName": "Name", "slug": "name" } ] }
- Call the
-
Generate a Unified JSON Schema
- Extract
fields
from each collection and store them as a structured JSON file:{ "BlogPosts": { "name": { "type": "PlainText", "required": true } }, "Products": { "title": { "type": "PlainText", "required": true }, "price": { "type": "Number", "required": true } } }
- Extract
-
Extend to TypeScript & Python
- Convert JSON schema into TypeScript types:
type BlogPost = { name: string; };
- Convert JSON schema into Zod types:
import { z } from "zod"; const BlogPostSchema = z.object({ name: z.string() });
- Convert JSON schema into Pydantic models:
from pydantic import BaseModel class BlogPost(BaseModel): name: str
- Convert JSON schema into TypeScript types:
I’m consciously ignoring some of the complexities of this step, but there are existing tools that could be a useful starting point for this, such as:
Caveat Regarding References and Multi-References
When working with more complex data types than the examples above, it’s important to note that raw field values alone do not always provide a complete representation of the data.
This is true, for instance, for fields that include references and multi-references, which depend on other collection types to be fully resolved.
For example, in my real Artists collection, there is a field "artist-tags"
which is a MultiReference field that links to another collection ("collectionId": "65801e578d8a3149071abcba"
).
Similarly, the "event"
field references the Events collection, meaning that the raw stored value is an ID that requires lookup in the referenced collection to obtain meaningful data.
This means that there is in fact a step 3.5
which takes the first-pass raw representation of the JSON schema, which includes embedded collection_id references, and transforms this into a real raw schema by referencing the other fetched schemas.
Without resolving these references, the typesafety would not extend to complex types - so it’s important to keep this in mind.
Final Thoughts
This simple addition to the Webflow CLI could:
- Provide instant type safety for developers.
- Reduce manual schema checking.
- Enhance DX by allowing Webflow to be the source of truth for types.
If there’s enough interest, I’d love to collaborate on this idea further! It’s likely I’ll be attempting some of this myself anyway to see feasibility, but I would love for this to be a collaborative effort so that others can take away value from this.
By the way, an example of this kind of workflow is in Supabase’s typescript integration - where the Supabase CLI can generate a typescript file that contains a schema of the postgres database. This script is automatically run as a pre-commit hook to ensure the schema is always up to date. The result is a FULLY TYPESAFE client for the Supabase API that understands the underlying data model and hence provides an extremely pleasant DX whilst interacting with the data. More info on this here: JavaScript API Reference | Supabase Docs
Thanks for reading, look forward to hearing some feedback on this