Concepts
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.
flags ─┐
prompts ─┼──▶ ProjectConfig ──▶ applyConfig()
--file ─┤ (validated) │
--ui ─┘ ├─ mode "new" ─▶ starter ─▶ base app ─▶ capability files ─▶ wiring ─▶ manifest ─▶ install
└─ mode "add" ─────────────────────────▶ capability files ─────────▶ manifest ─▶ installFour 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:
- 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 runcreate-vite(React) and/or write a lean Express app. - Writes capability files into
src/bsv/of each target. - Wires the base app (unless
--no-glue). It wraps<App />in<WalletProviders>, adds routes toApp.tsx, and mounts routes, CORS and the wallet relay in the server. - Writes the root runner when there's both a client and a server (
npm run devfor both). - Writes
AGENTS.mdandbsv-scaffold.json. - Adds dependencies to each
package.jsonand 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 new|add given? → use it
bsv-scaffold.json in the target? → add
React/Express project detected? → add
otherwise → newDefaults#
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.