src/, tests/, and configuration files always sit in the same relative positions, onboarding is faster and automated tooling — build scripts, test runners, and code generators — can make reliable assumptions about where things live.
Package Structure
Every library package underpackages/ follows this layout:
src/ tree shallow. If a package grows large enough to warrant subdirectories, introduce a single level of domain grouping (e.g., src/parsers/, src/validators/) before reaching for deeper nesting.
Application Structure
Applications underapps/ follow a similar convention. The example below shows a typical API service:
src/ subdirectory structure inside tests/ so the test for any given module is easy to locate.
Key Rules
1
Source code lives in src/
All TypeScript implementation files belong under
src/. Do not place runnable source files at the package root or inside tests/.2
Tests live in tests/
Keep all test files inside the top-level
tests/ directory. Do not colocate .test.ts or .spec.ts files next to their source counterparts inside src/.3
Public API is exported from src/index.ts
Consumers of your package import from the package name, which resolves to
src/index.ts. Only export symbols that are part of the intentional public API; keep internal modules unexported.4
No circular dependencies between packages
Packages must form a directed acyclic graph. Use a tool such as
madge to detect and prevent circular imports across the workspace.