Developer · Contributing
Developer Docs

Conventions that keep a monorepo mergeable

This repository is built by multiple agents and humans working in the same tree, often in parallel. These are the rules that make that survivable — they are all drawn from conventions the existing milestones actually followed.

Strict TypeScript is the bar

Every workspace compiles under strict: true, and the gate is:

run before you call anything done
npm run typecheck   # tsc --noEmit across all workspaces

A green typecheck is the minimum verification for any change; past milestones caught real bugs this way (untyped error-handler params, ??/|| precedence mistakes). If your change touches behavior, also record a functional verification — curl transcripts for api work, rendered-output checks for geometry work.

Declare file ownership before you edit

Parallel work in one tree only works with declared ownership: state the paths you own up front and do not edit outside them — no drive-by tweaks to other pages, shared components, lib files, or package.json files. If you need a shared component that doesn't exist, create it inside your owned paths rather than editing a communal file. Cross-imports are fine; cross-edits are not.

packages/shared is append-only

Both apps compile against @pacfully/shared, so changes there are additive: add new constants and types, never modify or remove existing exports in the same pass as a feature. After appending, rebuild the package before typechecking the apps:

after editing packages/shared
npm run build -w @pacfully/shared && npm run typecheck

Validate at the edge, in Fastify schemas

Request validation lives inline in each route as Fastify/ajv JSON schema — deliberately not zod, which is not in the dependency tree. Unknown fields are rejected (additionalProperties: false), and every failure surfaces through the single error handler as the shared ApiError shape. Keep new routes consistent: schema first, scoped queries (userId = request.user.sub), serialized responses.

The glass design system has rules

  • Tokens live in globals.css (Tailwind v4 @theme); components in components/glass/. Use the glass and text-accent utilities instead of hand-rolling surfaces.
  • The indigo→cyan gradient is reserved for primary CTAs and active states — never decoration.
  • Glass is for interactive surfaces (panels, toolbars, code blocks, tables). Backdrop blur never sits behind long-form body text.
  • Real content only: every string comes from the product, the template catalog, or the spec. No lorem ipsum, no stock placeholders, no fake screenshots.
  • Vary surfaces between adjacent sections — hairline lists, typographic blocks, glass cards, bare prose on the aurora field. Two identical patterns in a row is a bug.

Leave a build log

Every milestone ends with a build-log/NN-scope.md entry: what was created (with file paths), how it was verified (real commands and their results), and honest deviations from the spec. The log is how the next agent — human or AI — trusts the tree without re-verifying it. See build-log/02-backend.md and 03-editor.md for the house style.

Definition of done

  1. 1

    npm run typecheck passes in every affected workspace.

  2. 2

    Behavior verified by running it — curl flows, rendered output, or the dev server — not by reading code.

  3. 3

    No edits outside declared ownership; shared-package changes are additive and rebuilt.

  4. 4

    UI changes follow the design-system rules above and contain real content only.

  5. 5

    A build-log entry records what changed, the verification, and every deviation.