windo/Guides/The CLI
Guides

The CLI

The windo bin is the zero-config way in. Point it at the folder that holds your windo.config.ts and *.windo.tsx files and it boots a Vite dev server — already wired with the windo plugin — and prints the URL. You own no vite.config.ts; the CLI carries all of it. When you're ready to share the canvas, the same bin builds it to static files.

One command, no Vite config

The Vite plugin is the engine: it pairs @vitejs/plugin-react with windo, serves the workbench chrome and the preview iframe, and discovers your windos. The CLI exists so you don't have to assemble that yourself. Under the hood it calls Vite's createServer with windoPlugin already in the plugins array, then listens — so there's nothing for you to configure when all you want is to look at your components.

Reach for the plugin directly only when windo has to share a Vite config with something else (an existing app, custom resolve aliases, extra plugins). Otherwise the bin is the whole story.

Running it

The package installs a windo bin. The first positional argument is the commanddev (the default), build, or preview. With no command, dev is implied, so these two lines are equivalent:

SHELL
windo            # 'dev' is implied
windo dev

The next positional is the root — the directory Vite treats as the project base, and where windo looks for windo.config.ts and every *.windo.tsx matching your config's include glob. Omit it and the root is your current working directory; pass one to scope discovery to a subfolder.

SHELL
windo dev            # root = cwd
windo dev ./src      # root = ./src

Most projects don't run the bin globally — they pin it in a package script so the whole team gets the same command. The dependency lives in devDependencies and the script invokes the local bin.

JSONpackage.json
{
"scripts": {
  "windo": "windo dev ./src --port 6006"
},
"devDependencies": {
  "@westopp/windo": "^0.1.0"
}
}

Flags

Everything after the root is options. They map onto the dev server Vite spins up.

SHELL
windo dev ./src --port 6006 --open
windo dev --host
windo dev --config ./tools/windo.config.ts
  • -p, --port <n> sets the port to listen on. Without it, Vite picks its default (5173, or the next free port).
  • --host [host] exposes the server on your network so another device can reach the workbench. Pass it bare to bind every interface, or give it a specific host.
  • -o, --open opens the workbench in your browser as soon as the server is ready.
  • -c, --config <p> points at a windo.config.ts somewhere other than the root — useful when your config lives outside the directory you're serving.
  • -h, --help prints usage and exits without starting anything.

Building a static canvas

windo build compiles the workbench to a folder of static files — the chrome, the preview iframe, and every windo, bundled and hashed. The result is a plain windo-static/ you can drop on any static host (Netlify, Vercel, GitHub Pages, S3, a bare file server) to share the canvas with people who aren't running it locally.

SHELL
windo build              # build cwd → ./windo-static
windo build ./src        # build a subfolder root
windo build -d out       # write to ./out instead
windo build -b /canvas/  # set a non-root public base

It writes index.html at the root of the output and the preview document at __windo/iframe.html. The output directory defaults to windo-static/ — not dist/ — so a windo build never clobbers the dist/ your own app's build already owns. The public base defaults to ./ (relative), so the bundle works unchanged whether it's served from a domain root or a subpath — you don't rebuild to move it. Pass -b, --base to pin an absolute base when a host needs one.

  • -d, --outDir <p> — output directory. Defaults to windo-static.
  • -b, --base <p> — public base path. Defaults to ./.
  • -c, --config <p> — path to windo.config.ts, same as dev.

The build is self-contained: it does not read a vite.config.ts from your project, so the canvas never inherits an unrelated app's config. Reach for the plugin + vite build directly when you want that control.

Previewing a build

windo preview serves a built windo-static/ locally — the same files a static host would serve, on a local URL — so you can check it before you deploy.

SHELL
windo build && windo preview
windo preview -d out --port 6006 --open

It takes -d, --outDir (which folder to serve, default windo-static) plus the same --port, --host, and --open flags as dev. Run build first — preview only serves what's already on disk, it doesn't compile.

Where next

  • The Vite plugin — what the CLI boots for you, and how to wire windoPlugin into your own Vite config when you need to.
  • Writing a windo — author the *.windo.tsx files the dev server discovers and previews.