Skip to content
create-bsv-app

How it works

One config, one pipeline. How your flags, prompts or JSON become a ProjectConfig, and what the CLI does with it in new and add mode.

Under the hood, create-bsv-app is small and predictable. However you call it, it builds one ProjectConfig object and hands it to one function. Knowing that makes every flag, prompt and error easier to reason about.

the pipeline
 flags ─┐
prompts ─┼──▶  ProjectConfig  ──▶  applyConfig()
 --file ─┤        (validated)          │
   --ui ─┘                             ├─ mode "new" ─▶ starter ─▶ base app ─▶ capability files ─▶ wiring ─▶ manifest ─▶ install
                                       └─ mode "add" ─────────────────────────▶ capability files ─────────▶ manifest ─▶ install

Four ways in#

All four produce the same ProjectConfig, so the same config always takes the same path through the pipeline. They only differ in how you supply it.

Way in Command Best for
Prompts npx create-bsv-app@latest exploring, first run
Flags … --starter full-stack --capabilities wallet-login --yes scripts, docs, muscle memory
Config file … --dir my-app --file config.json CI, AI agents, reproducible setups
Browser UI … --ui --dir my-app point and click

You can mix them. Flags fill in their answers and the prompts only ask about the rest. With --yes there are no prompts at all, and anything unspecified uses its default.

Deep diveWhat --ui actually starts

A tiny HTTP server bound to 127.0.0.1 (never reachable from your network) serves a one-page form, generated from the same schema the terminal prompts use. Press Generate and it runs the same pipeline, then shuts itself down. It's single-use by design.

Modes#

new#

Creates a project in an empty directory (a .git folder or a bsv-scaffold.json is allowed). In order, it:

  1. Clones or generates the base. Complete examples are git cloned, and that's nearly the end: the manifest is written and dependencies installed. Generated starters run create-vite (React) and/or write a lean Express app.
  2. Writes capability files into src/bsv/ of each target.
  3. Wires the base app (unless --no-glue). It wraps <App /> in <WalletProviders>, adds routes to App.tsx, and mounts routes, CORS and the wallet relay in the server.
  4. Writes the root runner when there's both a client and a server (npm run dev for both).
  5. Writes AGENTS.md and bsv-scaffold.json.
  6. Adds dependencies to each package.json and installs them (unless --skip-install).

add#

Adds capabilities to an existing project. No base generator runs, and your own files are never edited. It writes capability files, AGENTS.md (with manual wiring snippets) and the manifest, adds dependencies, and installs. Existing helper files are kept unless you pass --force. Full guide.

How the mode is chosen#

mode inference
--mode new|add given?                 → use it
bsv-scaffold.json in the target?      → add
React/Express project detected?       → add
otherwise                             → new

Defaults#

Everything has one, so --yes with nothing else is valid as long as the starter determines a stack:

Field Default
directory .
name the directory name
starter custom
capabilities wallet-connect (always included in new)
bsvDir src/bsv
packageManager npm
network test
glue on
install on

Why generate, rather than ship a library?#

A library hides the code that decides who's logged in, and that's the code you most need to read and own. Generated files are yours: readable, editable and deletable, with no version lock-in and no magic. The heavy cryptography still comes from maintained packages (@bsv/sdk, @bsv/auth, @bsv/wallet-relay). The scaffold is the thin, visible layer between them and your app.