Skip to content

flowmetelev/wfkit

wfkit

wfkit is a CLI for Webflow code projects.

Use it to:

  • scaffold a new project
  • develop against your published .webflow.io site through a local proxy
  • migrate inline Webflow custom code into page and global source files
  • publish production bundles back to Webflow

Install the CLI

Run:

npm install -g @flowmetelev/wfkit

The npm package currently ships native binaries for:

  • macOS x64 and arm64
  • Linux x64 and arm64
  • Windows x64 and arm64

If your package manager blocks postinstall scripts, the wfkit launcher will download the native binary automatically on first run.

Then:

wfkit --help

Start a new project

Run:

wfkit init --name my-site

Add --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.md
  • package.json
  • wfkit.json
  • vite.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.ts is the one explicit global entry
  • src/features/* is for reusable behaviors that can be mounted from global or page entries
  • src/global/modules/* contains reusable global behaviors that you choose to import from the global entry
  • src/pages/*/index.ts is for per-page code
  • src/generated/wfkit-pages.ts contains generated page slug types for definePage(...)
  • src/utils/dom.ts contains low-level DOM helpers
  • src/utils/webflow.ts contains DRY mount helpers that align page and feature bootstrapping with the Webflow runtime
  • docs/index.md is the default markdown entry for the docs hub page
  • dist/assets/wfkit-manifest.json is generated during build and used by wfkit to resolve the correct output files

Publish a docs hub page

wfkit can render one markdown file into a dedicated Webflow docs page.

The default scaffold creates:

docs/index.md

Publish it with:

wfkit docs

By 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.

Develop through the local proxy

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-site

Then:

bun install

Then:

bun run dev

When Webflow pages are added or renamed, refresh typed page names in the scaffold with:

bun run pages:types

This 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.25

This uses the provided host in local script URLs and binds the proxy/dev server so the site can be reached outside localhost.

Publish production code

When you're ready to ship, run:

wfkit publish --env prod

This flow:

  1. builds your project
  2. pushes the build to GitHub
  3. updates the Webflow custom code
  4. 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 inline

Or 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-run

This still builds the project and checks Webflow, but it won't push, update code, or republish the site.

License

wfkit is licensed under GPL-3.0-only. See LICENSE.

Migrate existing Webflow code

If your Webflow project already has inline custom code, you can migrate it into the generated file structure:

wfkit migrate --dry-run

Then apply it:

wfkit migrate

What 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 --publish

That extended flow:

  1. writes the migrated local files
  2. builds the project
  3. if deliveryMode is cdn, pushes the artifact branch
  4. updates Webflow using either jsDelivr URLs or managed inline scripts

Release the CLI

wfkit uses the version in npm/package.json as the single release version.

The simplest release flow is:

task release:patch

Or:

task release:minor
task release:major

These commands already:

  1. validate the release version metadata
  2. run the npm installer test
  3. run go test ./...
  4. require a clean working tree before bumping
  5. bump the version in npm/package.json
  6. 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:major

After that:

  1. push your branch
  2. open and merge the PR into main
  3. 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:

  1. make and commit your feature changes in a branch
  2. run one command: task release:patch, task release:minor, or task release:major
  3. push the branch and open a pull request
  4. merge into main
  5. let GitHub Actions cut the release automatically

Check your setup

Run:

wfkit doctor

This checks:

  • wfkit.json
  • package.json
  • package manager and git
  • configured ports
  • Webflow authentication
  • whether the local dev server is already reachable

Use the commands

wfkit init

Create a new project scaffold.

The scaffold is TypeScript-first and installs dependencies by default unless you pass --skip-install.

Options:

  • --name Project name
  • --pages-dir Directory for page scripts
  • --global-entry Global entry file
  • --global-var Global variable name
  • --init-git Initialize a local git repository
  • --skip-install Skip dependency installation after generating the scaffold
  • --force Allow writing scaffold files into an existing non-empty directory
  • --package-manager Package manager: bun, npm, yarn, pnpm

wfkit proxy

Run the local reverse proxy for your published site.

Options:

  • --site-url Published .webflow.io URL
  • --script-url Custom local script URL
  • --dev-port Local Vite port
  • --dev-host Local Vite host
  • --proxy-port Local proxy port
  • --proxy-host Local proxy host
  • --open Open the proxied site automatically

wfkit publish

Publish code to Webflow.

Options:

  • --env prod or dev
  • --by-page Publish scripts per page
  • --dry-run Show what would change without pushing or updating Webflow
  • --script-url Override the generated script URL
  • --dev-port Local dev server port for legacy dev mode
  • --dev-host Local dev server host for legacy dev mode
  • --custom-commit Custom Git commit message for the asset branch publish
  • --delivery Production delivery mode: cdn or inline
  • --asset-branch Git branch used for published build artifacts and jsDelivr URLs
  • --build-dir Build output directory
  • --notify Show a desktop notification and play a sound when finished
  • --update Check for CLI updates before publish

wfkit docs

Render markdown and publish it to a dedicated Webflow docs page.

Options:

  • --file Markdown entry file for the docs hub
  • --page-slug Target Webflow page slug
  • --selector Selector used to mount the rendered docs content
  • --dry-run Show what would be changed without updating Webflow
  • --publish Publish the site after updating the docs page
  • --notify Show a desktop notification and play a sound when finished

wfkit pages

Inspect and manage Webflow pages without opening the Designer.

Subcommands:

  • wfkit pages list List static Webflow pages
  • wfkit pages create --name "Docs" --slug docs Create a static Webflow page
  • wfkit pages update --page-slug docs --seo-title "Docs" --seo-description "..." Update page metadata and SEO fields
  • wfkit pages inspect --slug docs Inspect one page and its managed custom code blocks
  • wfkit pages delete --slug docs --yes Delete one static Webflow page
  • wfkit pages open --slug docs Open the published Webflow page in your browser
  • wfkit pages types Generate src/generated/wfkit-pages.ts from 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

wfkit cms

Inspect Webflow CMS collections and sync them as local JSON files for versioned review.

Subcommands:

  • wfkit cms collections List CMS collections for the current site
  • wfkit cms pull Pull all CMS collections into webflow/cms
  • wfkit cms pull --collection blog-posts Pull one collection by slug or id
  • wfkit cms pull --dir webflow/cms --target production Pull the production item view instead of staging
  • wfkit cms diff Compare local CMS JSON against the current Webflow state
  • wfkit cms push Apply local CMS JSON changes back to Webflow
  • wfkit cms push --delete-missing Delete remote items that no longer exist in local JSON

wfkit cms pull writes:

  • webflow/cms/database.json database metadata for the current site
  • webflow/cms/<collection-slug>/schema.json collection schema and field definitions
  • webflow/cms/<collection-slug>/items/*.json one file per CMS item

Recommended workflow:

  1. wfkit cms pull
  2. edit the JSON files you want to change
  3. wfkit cms diff
  4. wfkit 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

wfkit migrate

Migrate inline Webflow custom code into local source files.

Options:

  • --dry-run Show the migration plan without writing files or updating Webflow
  • --force Overwrite existing generated migration targets
  • --publish After writing local files, build assets, push the artifact branch, and update Webflow
  • --custom-commit Custom Git commit message for the generated migration publish
  • --delivery Delivery mode for --publish: cdn or inline
  • --asset-branch Git branch used for published build artifacts and jsDelivr URLs
  • --build-dir Build output directory
  • --notify Show 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 in buildDir to the asset branch, then point Webflow at jsDelivr
  • inline: 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.

wfkit update

Check whether a newer CLI version is available.

wfkit doctor

Validate your local environment and Webflow auth.

Legacy dev mode

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.

Contributing

Take a look at CONTRIBUTING.md.

Thanks

wfkit uses kooky to load browser cookies for Webflow authentication.

Thanks to the browserutils/kooky maintainers for the library this workflow builds on.

About

CLI for Webflow code projects

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors