← All decisions

pnpm monorepo with apps/* and packages/*

accepted

0001 — pnpm monorepo with apps/* and packages/*

  • Status: accepted
  • Date: 2026-05-06
  • Deciders: Derek

Context

Ark is one codebase serving N tenants across three deployable surfaces (public site, admin portal, API). The codebase will share substantial logic between surfaces (auth, permissions, CMS reads, types, config schemas). Cross-cutting changes — most notably “add organization_id to every table and propagate through every layer” — must land atomically.

We’re also optimizing for AI agents to do non-trivial work. Agents are most productive when they can see the entire system in one tree without fetching from N remotes.

Decision

A single git repository with pnpm workspaces. Layout: apps/{api,admin,site} (deployable surfaces) + packages/* (shared libraries) + supabase/migrations (CLI-managed migrations, see ADR 0012) + tenants/* (per-tenant config) + docs/.

pnpm specifically: workspaces are first-class, install is fast, --filter semantics are clean for CI partitioning, and the lockfile reliably reflects what’s installed (npm’s lockfile drift has burned us before in internalize).

Consequences

Easier:

  • Schema migrations + package + app changes ship in one PR
  • Agents read the whole system without cross-repo navigation
  • Type changes propagate at compile time
  • Single CI pipeline; one place to look for failures
  • Refactors that touch every layer (renames, signature changes) are mechanical

Harder:

  • CI must be smart about which packages to test on which changes (mitigated by pnpm --filter ...)
  • Per-tenant private content (logos, custom themes) needs a story — it lives in tenants/<slug>/ with .gitignore for sensitive material, or in a separate private repo per tenant
  • Build artifacts must be carefully scoped per app

Revisit if: install times exceed 90s on developer machines, or if the consulting agency wants to fork-and-modify ark for one of their clients (then we need a “ship a snapshot” story).

Alternatives considered

  • Multi-repo with npm-published packages. Cleanest dependency boundaries, but cross-cutting changes become 5-PR coordination dances. Not viable for one engineer + AI agents.
  • Yarn workspaces / npm workspaces. Both technically work; pnpm wins on speed and --filter ergonomics. Internalize uses npm; we don’t carry that forward because pnpm is strictly better for the workspace use case.
  • Nx / Turborepo. Good build orchestration tools; both add a layer of “magic” we don’t yet need at this scale. We can adopt Turbo later if pnpm-only build perf becomes a bottleneck.