Skip to content

Dependency boundaries

Nx tags enforce the direction recorded in architecture/contract.json. The current roles are app, application, capability, kernel, adapter, and design-system.

Consumer roleMay depend on
appapplication, capability, kernel, adapter, design-system, app
applicationapplication, capability, kernel, adapter, design-system
capabilitycapability, kernel, adapter, design-system
adapteradapter, kernel
design-systemdesign-system, kernel, adapter
kernelkernel only

The graph is intentionally asymmetric. A reusable kernel cannot reach into product capabilities, and a capability cannot depend on application orchestration.

Cross-library imports use the @trinity/* aliases declared in tsconfig.base.json. A library’s src/index.ts is its public API. Import internal files relatively only from within the same library.

Features never import other feature libraries. Shared behavior moves to the owning data-access capability, an application-level orchestrator, or a genuinely domain-neutral component or utility. matrix-js-sdk stays behind data-access services; components and feature pages do not import it.

Product UI imports @trinity/components/*. The Spartan and vendor layers sit behind that public component tier. Generated Spartan source remains generator-owned and is not a shortcut around the component boundary.

Inspect the exact projects and graph before adding an import:

Terminal window
pnpm nx show project feature-rooms --json
pnpm nx show project data-access-timeline --json
pnpm nx graph --print
pnpm architecture:check

The architecture check validates more than TypeScript resolution: it checks the repository contract, design-system edges, host boundaries, and registered E2E suites. A compiling deep import or untagged edge is not therefore an accepted dependency.

Use capability ownership to find the correct destination when an edge is rejected.