Monorepo Standards
Last reviewed: 2026-04-21
Maintained by: Engineering
This repo uses a pnpm workspace model. The goal of these rules is to keep dependencies, scripts, and shared code predictable.
Adding New Packages
Root devDependencies
Add packages to the root only if the tooling is shared across the whole repo, for example:
- ESLint
- TypeScript tooling
- repo-wide CLI tools
Example:
pnpm add -D eslint
Workspace Dependency
If a dependency is used by only one app, add it only to that workspace:
pnpm --filter @zgrid/api add zod
pnpm --filter @zgrid/manager-desk add clsx
Rule:
- an
apps/apidependency should not go into root if the web app does not use it - a Manager Desk dependency from
apps/manager-deskshould not go into root if the backend does not use it
Shared Packages in packages/*
If something is used by multiple apps, extract it into packages/*, for example:
- shared types
- shared validation schema
- generated API client
- shared config helpers
Do not copy the same utility or type into multiple apps if it already belongs in shared code.
Rules for pnpm-lock.yaml
- never edit it manually
- every dependency change must include the lockfile diff
- use
pnpm add,pnpm add -D, orpnpm --filter ... add - do not mix
npm installandpnpm addin this repo
If the lockfile looks unexpected:
- check whether you added the dependency to the correct workspace
- check whether you accidentally used root instead of
--filter
Script Rules
Root Scripts
Root package.json should contain only:
- common developer entrypoints
- standard check, migrate, and seed commands
- the most common team commands
Examples:
dev:apidev:manager-deskcheck:apicheck:manager-deskdb:migrate
Workspace Scripts
Each workspace package.json should contain app-specific scripts.
Examples:
devbuildchecklint
If a script only makes sense in one app, do not promote it to root without a good reason.
Shared Code Rules
Shared code belongs in packages/* when:
- it is used by more than one app
- it represents a stable contract
- it is worth versioning inside the monorepo
Examples of good shared code:
- DTO/type contract
- validation schema
- generated API client
Examples of code that should not be shared too early:
- a single helper used in one place only
- a UI-specific formatter used only by Manager Desk
- a backend-only DB helper that does not make sense outside the API
New Environment Variables
When you add a new environment variable, always update:
apps/api/src/config/env.tsor the relevant env loader.env.example- environment-contract.md
- ../04-operations/infrastructure.md ako utiče na deploy ili hosting
- GitHub Environments ako je potrebna u CI/CD ili deployu
Rule:
- an env change is not complete until all of the above are updated
Dependency Hygiene
Before adding a new package, check:
- whether the same or a similar package already exists in the repo
- whether an existing tool can be reused
- whether the dependency should really be runtime instead of devDependency
Do not add a package if:
- it solves a trivial problem we can already solve with the existing stack
- it introduces vendor lock-in without a clear reason
- it is only needed for an experimental flow without a real product need
Source of Truth
When you change monorepo rules or tooling, keep these aligned:
package.jsonpnpm-workspace.yamlpnpm-lock.yaml- monorepo-standards.md