# Project structure

> Every file a full-stack scaffold creates, what it does, and which ones are yours to change.

> Agents: search these docs with the `search_docs` tool on the MCP server at https://createbsvapp.vercel.app/mcp, or read everything at https://createbsvapp.vercel.app/llms-full.txt.

This is what `--starter full-stack --capabilities wallet-login,signed-requests` writes, minus create-vite's own assets and lint config. Other starters produce a subset: `react` is the `client/` half at the project root, and `express` is the `server/` half.

## The tree

```tree
my-app/
├── AGENTS.md                      # how each capability works, for humans and AI agents
├── bsv-scaffold.json              # what was generated (read by later `add` runs)
├── package.json                   # root runner: dev, build, install:apps
├── scripts/
│   └── run-apps.mjs               # starts client + server together
├── client/                        # Vite + React + TypeScript (from create-vite)
│   ├── package.json
│   ├── vite.config.ts
│   └── src/
│       ├── main.tsx               # wraps <App/> in <WalletProviders>
│       ├── App.tsx                # routes: /, /login, /signed-demo
│       └── bsv/
│           ├── config.ts          # API_BASE_URL, BSV_NETWORK (from VITE_* env)
│           ├── apiClient.ts       # the one fetch wrapper: bounded, no redirects
│           ├── auth.ts            # createAuthProof / verifyAuthProof
│           ├── serverIdentity.ts  # getServerIdentity() → GET /api/identity
│           ├── walletAcquisition.ts      # desktop wallet via WalletClient('auto')
│           ├── WalletConnectionContext.tsx  # mobile QR relay session
│           ├── WalletContext.tsx         # useWallet(): status, wallet, identityKey
│           ├── WalletProviders.tsx       # both providers in one component
│           ├── ConnectWallet.tsx         # the button + "no wallet" dialog
│           ├── Home.tsx                  # demo hub
│           ├── WalletLogin.tsx           # /login demo        (wallet-login)
│           ├── useWalletLogin.tsx        # login() hook       (wallet-login)
│           ├── SignedRequestDemo.tsx     # /signed-demo demo  (signed-requests)
│           ├── signedRequest.ts          # createSignedRequest (signed-requests)
│           ├── useSignedRequest.ts       # signedFetch() hook (signed-requests)
│           └── bsv.css                   # minimal demo styles
└── server/                        # Express 5 + TypeScript, run with tsx
    ├── package.json
    └── src/
        ├── index.ts               # routes, CORS, wallet relay, listen()
        └── bsv/
            ├── config.ts          # SERVER_PRIVATE_KEY, PORT, CLIENT_ORIGIN, BSV_NETWORK
            ├── auth.ts            # same proof helpers as the client
            ├── nonceStore.ts      # single-use nonces (in memory)
            ├── loginRoute.ts      # POST /api/login       (wallet-login)
            └── verifySignedRequest.ts  # framework-agnostic   (signed-requests)
```

## What runs where

| What | Client | Server |
| --- | --- | --- |
| Dev command | `vite` | `tsx watch src/index.ts` |
| Dev URL | http://localhost:5173 | http://localhost:3000 |
| Build | `tsc -b && vite build` → `client/dist` | `tsc` → `server/dist` |
| Start in production | any static host | `node dist/index.js` |

From the project root, `npm run dev` runs both dev commands, `npm run build` builds both, and `npm run install:apps` reinstalls both. Each app also works on its own: `cd client && npm run dev` is fine.

Client and server are **separate packages** with their own `package.json`, lockfile and `node_modules`. You can deploy them to different hosts, and add a database driver to the server without touching the client.

## Server routes

| Route | From | What it does |
| --- | --- | --- |
| `GET /health` | base | `{ "status": "ok" }` for load balancers |
| `GET /api/identity` | wallet-connect | the server's public identity key |
| `GET /api/session`, `/ws` | wallet-connect | mobile wallet pairing (QR relay) |
| `POST /api/login` | wallet-login | verifies a `login` proof, returns `{ identityKey }` |
| `POST /api/echo` | signed-requests | verifies a signed request, echoes the signer |

## Which files are yours?

**All of them.** Nothing is hidden in a package or framework. That said, they fall into three groups:

- **Edit freely:** `App.tsx`, `main.tsx`, `server/src/index.ts`, `Home.tsx`, the demo pages and `bsv.css`. These are starting points, and the demo pages are there to delete.
- **Read before you edit:** `config.ts`, `apiClient.ts`, `auth.ts`, `nonceStore.ts`, `serverIdentity.ts`. They're small but security-sensitive. See [Security model](https://createbsvapp.vercel.app/docs/security) for what each one guarantees.
- **Don't hand-edit:** `bsv-scaffold.json`. Later `add` runs read it to decide what's already installed.

::: tip Re-running is safe
Run `npx create-bsv-app@latest add --capabilities <id> --yes` later and existing helper files are left alone unless you pass `--force`. Your `App.tsx`, `main.tsx` and server entry are never touched in `add` mode. `AGENTS.md` is regenerated with the wiring snippets to paste. See [Add to an existing project](https://createbsvapp.vercel.app/docs/add-to-existing).
:::

::: deep Why are client and server `auth.ts` identical?
The proof format is the same on both sides. Shipping one tiny file to each package keeps them independently deployable, with no shared workspace package and no build step. Both wrap [`@bsv/auth`](https://www.npmjs.com/package/@bsv/auth).
:::

## Read `AGENTS.md` next

Every scaffold writes an `AGENTS.md` at the project root. For each installed capability it covers *how it works*, *how it's used* (exact function signatures and files) and *future integrations*. It's written for coding agents, and it's the best quick reference for humans too.
