boundary-violation issues in fallow dead-code output.
For preset descriptions, output formats, and suppression, see Architecture boundaries.
Presets
Fallow ships four built-in presets for common architecture patterns:| Preset | Zones | Description |
|---|---|---|
layered | 4 | Classic N-tier: presentation, application, domain, infrastructure |
hexagonal | 3 | Ports and adapters: adapters, ports, domain |
feature-sliced | 6 | Feature-Sliced Design: strict downward-only imports |
bulletproof | 4 | Bulletproof React: app, features, shared, server |
See Architecture boundaries - Presets for the full zone and rule definitions of each preset.
tsconfig rootDir detection
When a preset is active, fallow readscompilerOptions.rootDir from tsconfig.json to determine the source root for zone patterns. Preset zones become {rootDir}/{zone}/**.
The detection logic:
- Reads
tsconfig.jsonfrom the project root (supports JSONC with comments and trailing commas) - Extracts
compilerOptions.rootDir - Strips a leading
./prefix and any trailing/ - Rejects
.,.., and absolute paths for security - Falls back to
srcif the field is missing, the file doesn’t exist, or the value is rejected
tsconfig.json
hexagonal preset, this produces zones:
rootDir detection only applies to presets. Custom zones use patterns exactly as written.
Custom zones
Define zones manually when presets don’t match your architecture. Each zone has:| Field | Type | Description |
|---|---|---|
name | string | Zone identifier used in rules |
patterns | string[] | Glob patterns relative to the project root |
root | string? | Reserved for future use (currently ignored) |
- A file belongs to the first zone whose pattern matches (first-match wins)
- Files that don’t match any zone are unrestricted — they can import from and be imported by any zone
- Zone order matters: place more specific patterns before broader ones
Custom rules
Rules define which zones may import from which. Each rule has:| Field | Type | Description |
|---|---|---|
from | string | The importing zone |
allow | string[] | Zones that from may import from |
- Self-imports are always allowed — files within the same zone can freely import each other
- No rule entry means the zone is unrestricted — it can import from any zone
- Empty
allowlist means the zone is isolated — no cross-zone imports permitted - Only zones with an explicit rule entry are constrained
Merging presets with custom config
When bothpreset and zones/rules are specified, fallow merges them:
- Zones with the same name as a preset zone replace the preset zone entirely
- Rules with the same
fromas a preset rule replace the preset rule - New zones and rules are added on top of the preset
Example: override a preset zone
Use the hexagonal preset but put your domain code insrc/core instead of src/domain:
adapters and ports from the hexagonal preset but replaces the domain zone pattern with src/core/**. All three rules remain unchanged.
Example: add a zone to a preset
Add atest zone to the bulletproof preset so test utilities are isolated:
test zone and its rule are added on top.
Inspecting boundaries
Usefallow list --boundaries to see the expanded configuration after preset expansion and merging. This is the fastest way to verify your config is correct.
$ fallow list --boundaries
Common patterns
Monorepo with per-package boundaries
Monorepo with per-package boundaries
Preset zone patterns are flat (
src/<zone>/**), which doesn’t work when packages have separate source directories. Define zones explicitly for each package:tRPC apps with server-to-features imports
tRPC apps with server-to-features imports
In tRPC apps, the server router typically imports from feature modules to compose sub-routers. With the bulletproof preset, this causes Alternatively, add
server -> features violations.The cleanest approach is to suppress the router composition file:src/server/_app.ts
features to the server rule:Adding a test zone alongside a preset
Adding a test zone alongside a preset
Test files often need to import from any zone. Add a Since zones use first-match classification, place more specific patterns (like test file globs) before broader zone patterns. When using a preset with custom zones, custom zones are appended after preset zones. If your test files live inside zone directories (e.g.,
test zone that sits above the preset layers:src/features/auth/auth.test.ts), the preset’s features zone pattern will match first. Move the test patterns into an explicit zone list that comes before the preset zones, or use ignorePatterns to exclude test files from boundary analysis entirely.See also
Architecture boundaries
Presets, output formats, and inline suppression for boundary violations.
Rules & Severity
Set
boundary-violation to error, warn, or off.Inline Suppression
Suppress individual findings in source code.