# Contributing ## Local setup ```bash yarn install # node 20+, yarn 4 via corepack yarn setup # downloads the PocketBase binary for your OS yarn dev # webapp on :3000, PocketBase on :8090, shared in watch mode ``` Create a PocketBase superuser: `yarn workspace @garage-ware/pb admin `. Promote an existing app user to admin: `yarn workspace @garage-ware/pb seed-admin `. `shared/dist/` must exist for `webapp` to compile — run `yarn workspace @garage-ware/shared build` after pulling or editing `shared/src/`. ## Scripts ```bash yarn build # all workspaces yarn test # every test lives in webapp yarn lint # autofix yarn lint:check | typecheck | format | format:check yarn precommit # build:shared + lint + typecheck + format + test yarn db:migrate # generate migrations from shared/src/schema/ yarn db:status # check migration sync state ``` CI ([.github/workflows/ci.yml](.github/workflows/ci.yml)) runs `install --immutable` → `build` → `format:check` → `lint:check` → `typecheck` → `test`. Match that order locally before pushing. Conventional commits are load-bearing — release-please derives the version and changelog from them. ## Adding a collection Schemas are the source of truth; migrations are generated from them. 1. Create `shared/src/schema/.ts` with `defineCollection()` plus the zod field helpers (`TextField`, `RelationField`, `BoolField`, …). Export the collection, `Schema`, `InputSchema` and the inferred types. 2. Re-export from [shared/src/schema.ts](shared/src/schema.ts). 3. Create `shared/src/mutators/.ts` extending `BaseMutator` ([shared/src/mutators/base.ts](shared/src/mutators/base.ts)); re-export from the mutators index. 4. Add a collection overload in [webapp/src/lib/types.ts](webapp/src/lib/types.ts). 5. `yarn workspace @garage-ware/shared build && yarn db:migrate`, review the generated file in [pocketbase/pb_migrations/](pocketbase/pb_migrations/), then restart PocketBase — it auto-applies on startup. A rule that references another collection needs that collection created first, so rename generated files if their timestamps order the dependencies wrongly. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#adding-a-collection) for the current `yarn db:migrate` caveat and hand-written migration examples. ## Invariants worth knowing before you start - **Client-side PocketBase only** — no PB from a Server Component. See [docs/PB_SSR.md](docs/PB_SSR.md). - **The Garage client is server-only** — everything under `webapp/src/lib/garage/` is `import 'server-only'`; the admin token must never reach the browser. - **Mutators, not the raw SDK** for PocketBase reads. - **Schema → migration → restart** after editing `shared/src/schema/`. The full account of every boundary, and what broke when it wasn't there, is in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). [CLAUDE.md](CLAUDE.md) is the condensed rule list.