wfkit is a CLI for Webflow code projects.
Use it to:
- scaffold a new project
- develop against your published
.webflow.iosite through a local proxy - migrate inline Webflow custom code into page and global source files
- publish production bundles back to Webflow
Run:
npm install -g @flowmetelev/wfkitThe npm package currently ships native binaries for:
- macOS
x64andarm64 - Linux
x64andarm64 - Windows
x64andarm64
If your package manager blocks postinstall scripts, the wfkit launcher will download the native binary automatically on first run.
Then:
wfkit --helpRun:
wfkit init --name my-siteAdd --init-git if you want the scaffold to initialize a local repository immediately.
Add --skip-install if you only want the files and do not want to install dependencies yet.
Use --force if you explicitly want to write scaffold files into an existing non-empty directory.
This creates a new folder in your current directory:
my-site/
Inside it, wfkit generates:
README.mdpackage.jsonwfkit.jsonvite.config.js.gitignore.prettierrc.prettierignore.editorconfig
wfkit.json is the main project config file. That's where you keep your Webflow and GitHub settings.
Example:
{
"appName": "my-site",
"siteUrl": "https://my-site.webflow.io",
"ghUserName": "your-username",
"repositoryName": "your-repo",
"packageManager": "bun",
"assetBranch": "wfkit-dist",
"deliveryMode": "cdn",
"buildDir": "dist/assets",
"devHost": "localhost",
"devPort": 5173,
"proxyHost": "localhost",
"proxyPort": 3000,
"openBrowser": true,
"globalEntry": "src/global/index.ts",
"docsEntry": "docs/index.md",
"docsPageSlug": "docs"
}The generated project is organized for Webflow:
src/
features/
site-status.ts
global/
index.ts
modules/
site.global.ts
pages/
home/
index.ts
utils/
dom.ts
webflow.ts
build/
webflow-vite-plugin.js
docs/
index.md
dist/assets/
wfkit-manifest.json
How it works:
src/global/index.tsis the one explicit global entrysrc/features/*is for reusable behaviors that can be mounted from global or page entriessrc/global/modules/*contains reusable global behaviors that you choose to import from the global entrysrc/pages/*/index.tsis for per-page codesrc/generated/wfkit-pages.tscontains generated page slug types fordefinePage(...)src/utils/dom.tscontains low-level DOM helperssrc/utils/webflow.tscontains DRY mount helpers that align page and feature bootstrapping with the Webflow runtimedocs/index.mdis the default markdown entry for the docs hub pagedist/assets/wfkit-manifest.jsonis generated during build and used bywfkitto resolve the correct output files
wfkit can render one markdown file into a dedicated Webflow docs page.
The default scaffold creates:
docs/index.md
Publish it with:
wfkit docsBy default this targets the Webflow page with slug docs.
If that page does not exist yet, wfkit docs now creates it automatically before syncing the managed docs block.
The command injects a managed docs block into that page's custom code and mounts the rendered content into:
[data-wf-docs-root], if present- otherwise
main
If you want a specific mount point, add an element with data-wf-docs-root to the Webflow page.
The recommended dev flow is proxy, not publish --env dev.
proxy leaves the live Webflow site alone. It proxies your published .webflow.io site locally, removes managed production scripts from proxied HTML, and injects your local Vite scripts only in the browser you use for development.
Run:
cd my-siteThen:
bun installThen:
bun run devWhen Webflow pages are added or renamed, refresh typed page names in the scaffold with:
bun run pages:typesThis starts:
- Vite on
http://localhost:5173 - the Webflow proxy on
http://localhost:3000
Open:
http://localhost:3000
Use wfkit proxy directly if you want to override ports or hosts.
If you want to open the proxied site from another device on your network, run:
wfkit proxy --host 192.168.1.25This uses the provided host in local script URLs and binds the proxy/dev server so the site can be reached outside localhost.
When you're ready to ship, run:
wfkit publish --env prodThis flow:
- builds your project
- pushes the build to GitHub
- updates the Webflow custom code
- republishes the site
By default, production publish uses deliveryMode: "cdn" and points Webflow at the artifact branch through jsDelivr.
If you want to skip jsDelivr and write the built module code back into Webflow as managed inline scripts, run:
wfkit publish --env prod --delivery inlineOr set this once in wfkit.json:
{
"deliveryMode": "inline"
}If you want to preview the publish plan without changing GitHub or Webflow, run:
wfkit publish --env prod --dry-runThis still builds the project and checks Webflow, but it won't push, update code, or republish the site.
wfkit is licensed under GPL-3.0-only. See LICENSE.
If your Webflow project already has inline custom code, you can migrate it into the generated file structure:
wfkit migrate --dry-runThen apply it:
wfkit migrateWhat migrate does:
- reads page-level inline scripts from Webflow
- creates page migration modules using page slugs, for example
src/pages/about/webflow.migrated.ts - wires those migrated modules into the local page entry, for example
src/pages/about/index.ts - moves migratable global inline code into
src/global/modules/webflow.migrated.ts - leaves publishing as a separate explicit step so you can review the diff first
Use --force if a target page or global migration file already exists and you want to overwrite it.
If you want the old one-shot behavior after writing local files, run:
wfkit migrate --publishThat extended flow:
- writes the migrated local files
- builds the project
- if
deliveryModeiscdn, pushes the artifact branch - updates Webflow using either jsDelivr URLs or managed inline scripts
wfkit uses the version in npm/package.json as the single release version.
The simplest release flow is:
task release:patchOr:
task release:minor
task release:majorThese commands already:
- validate the release version metadata
- run the npm installer test
- run
go test ./... - require a clean working tree before bumping
- bump the version in
npm/package.json - create a commit like
chore: release vX.Y.Z
If you only want to bump the version without creating a commit, use:
task version:patch
task version:minor
task version:majorAfter that:
- push your branch
- open and merge the PR into
main - GitHub Actions creates the release automatically if that version tag does not already exist
The npm publish step uses npm trusted publishing via GitHub Actions OIDC.
It does not require NPM_TOKEN when npm trusted publishing is configured correctly.
Trusted publisher settings for @flowmetelev/wfkit:
- owner:
flowmetelev - repository:
wfkit - workflow file:
publish.yml - environment name:
main
If the version in npm/package.json hasn't changed, the release workflow skips itself.
Typical flow:
- make and commit your feature changes in a branch
- run one command:
task release:patch,task release:minor, ortask release:major - push the branch and open a pull request
- merge into
main - let GitHub Actions cut the release automatically
Run:
wfkit doctorThis checks:
wfkit.jsonpackage.json- package manager and
git - configured ports
- Webflow authentication
- whether the local dev server is already reachable
Create a new project scaffold.
The scaffold is TypeScript-first and installs dependencies by default unless you pass --skip-install.
Options:
--nameProject name--pages-dirDirectory for page scripts--global-entryGlobal entry file--global-varGlobal variable name--init-gitInitialize a local git repository--skip-installSkip dependency installation after generating the scaffold--forceAllow writing scaffold files into an existing non-empty directory--package-managerPackage manager:bun,npm,yarn,pnpm
Run the local reverse proxy for your published site.
Options:
--site-urlPublished.webflow.ioURL--script-urlCustom local script URL--dev-portLocal Vite port--dev-hostLocal Vite host--proxy-portLocal proxy port--proxy-hostLocal proxy host--openOpen the proxied site automatically
Publish code to Webflow.
Options:
--envprodordev--by-pagePublish scripts per page--dry-runShow what would change without pushing or updating Webflow--script-urlOverride the generated script URL--dev-portLocal dev server port for legacydevmode--dev-hostLocal dev server host for legacydevmode--custom-commitCustom Git commit message for the asset branch publish--deliveryProduction delivery mode:cdnorinline--asset-branchGit branch used for published build artifacts and jsDelivr URLs--build-dirBuild output directory--notifyShow a desktop notification and play a sound when finished--updateCheck for CLI updates before publish
Render markdown and publish it to a dedicated Webflow docs page.
Options:
--fileMarkdown entry file for the docs hub--page-slugTarget Webflow page slug--selectorSelector used to mount the rendered docs content--dry-runShow what would be changed without updating Webflow--publishPublish the site after updating the docs page--notifyShow a desktop notification and play a sound when finished
Inspect and manage Webflow pages without opening the Designer.
Subcommands:
wfkit pages listList static Webflow pageswfkit pages create --name "Docs" --slug docsCreate a static Webflow pagewfkit pages update --page-slug docs --seo-title "Docs" --seo-description "..."Update page metadata and SEO fieldswfkit pages inspect --slug docsInspect one page and its managed custom code blockswfkit pages delete --slug docs --yesDelete one static Webflow pagewfkit pages open --slug docsOpen the published Webflow page in your browserwfkit pages typesGeneratesrc/generated/wfkit-pages.tsfrom the current Webflow pages
wfkit pages update can change:
- title and slug
- SEO title and description
- search title and description
- canonical URL
- sitemap inclusion
- search exclusion
Inspect Webflow CMS collections and sync them as local JSON files for versioned review.
Subcommands:
wfkit cms collectionsList CMS collections for the current sitewfkit cms pullPull all CMS collections intowebflow/cmswfkit cms pull --collection blog-postsPull one collection by slug or idwfkit cms pull --dir webflow/cms --target productionPull the production item view instead of stagingwfkit cms diffCompare local CMS JSON against the current Webflow statewfkit cms pushApply local CMS JSON changes back to Webflowwfkit cms push --delete-missingDelete remote items that no longer exist in local JSON
wfkit cms pull writes:
webflow/cms/database.jsondatabase metadata for the current sitewebflow/cms/<collection-slug>/schema.jsoncollection schema and field definitionswebflow/cms/<collection-slug>/items/*.jsonone file per CMS item
Recommended workflow:
wfkit cms pull- edit the JSON files you want to change
wfkit cms diffwfkit cms push
wfkit cms push is safe by default:
- it creates new items that exist locally but not in Webflow
- it updates existing items when local JSON changed
- it does not delete remote items unless you pass
--delete-missing
Migrate inline Webflow custom code into local source files.
Options:
--dry-runShow the migration plan without writing files or updating Webflow--forceOverwrite existing generated migration targets--publishAfter writing local files, build assets, push the artifact branch, and update Webflow--custom-commitCustom Git commit message for the generated migration publish--deliveryDelivery mode for--publish:cdnorinline--asset-branchGit branch used for published build artifacts and jsDelivr URLs--build-dirBuild output directory--notifyShow a desktop notification and play a sound when finished
wfkit publish and wfkit migrate --publish support two delivery modes:
cdn: publish only the built files inbuildDirto the asset branch, then point Webflow at jsDelivrinline: build self-contained bundles and write them back into Webflow as managed inline module scripts
Neither command commits or pushes your working tree source files.
Check whether a newer CLI version is available.
Validate your local environment and Webflow auth.
wfkit publish --env dev is still available, but it's now the advanced path.
Use it only if you explicitly want wfkit to inject a dev script into Webflow and roll it back later. For everyday development, proxy is safer because other people visiting the site won't see your local setup.
Take a look at CONTRIBUTING.md.
wfkit uses kooky to load browser cookies for Webflow authentication.
Thanks to the browserutils/kooky maintainers for the library this workflow builds on.