Skip to Content
Living documentation — last reviewed 2026-05-28
DecisionsADR-0001: Nx monorepo, pnpm workspaces

ADR-0001: Nx monorepo, pnpm workspaces

Status: Accepted Date: ~2026-01 (estimate; predates this doc) Context owner: Owner

Context

FitKit ships at least three runtime artifacts that share types and validation:

  • A NestJS API (apps/api).
  • A Next.js web app (apps/web).
  • A standalone Vite admin app (apps/admin).

Plus secondary surfaces: an Astro marketing site (apps/marketing) and an Astro per-org minisite app (apps/minisites). Future surfaces planned: a native mobile app, a WhatsApp bot.

Sharing TypeScript types, Zod schemas, and the Drizzle database client across these would either require publishing internal packages (yak-shaving) or a monorepo.

Decision

Use Nx to manage a single repository, with pnpm workspaces as the package manager. Two shared libraries:

  • libs/shared (@fitkit/shared) — Zod schemas + TypeScript types consumed by both API and frontends.
  • libs/db (@fitkit/db) — Drizzle ORM schema definitions + createDbClient factory.

Path aliases in tsconfig.base.json:

  • @fitkit/sharedlibs/shared/src/index.ts
  • @fitkit/dblibs/db/src/index.ts

Consequences

Positive

  • Shared schemas are imported, not duplicated. Changing an API response shape immediately surfaces type errors in the web client.
  • Nx affected-graph powers efficient CI: only projects touched by a PR re-run.
  • One pnpm lockfile, one set of tooling configs, one source of truth.

Negative

  • New engineers must learn Nx (the nx <target> <project> invocation isn’t standard npm-workspace muscle memory).
  • A breaking change to libs/shared can ripple through every app. We mitigate via the type system — there are no untyped boundaries.
  • Cross-project tasks are coupled in CI; one slow project slows the whole pipeline. Mitigation: concurrency.cancel-in-progress, per-project timeouts.

Alternatives considered

  • Separate repos with published internal packages. Higher overhead, slower iteration, and the org isn’t big enough to need the isolation.
  • Turborepo. Comparable feature set; Nx was chosen for its richer plugin ecosystem (NestJS, Next.js, etc.) and the affected-graph being more capable at the time.