Skip to main content
fallow dead-code enforces architecture boundaries by checking that imports between directories follow your rules. Define and declare which zones may import from which.
fallow dead-code --boundary-violations
Boundary violations are included in fallow dead-code output by default. Use --boundary-violations to show only boundary issues.

Quick start with presets

The fastest way to add boundaries is with a built-in preset. Fallow ships four presets for common architecture patterns:
{
  "boundaries": {
    "preset": "bulletproof"
  }
}
Run fallow list --boundaries to see the expanded zones and rules:
$ fallow list --boundaries
Boundaries: 4 zones, 4 rules

Zones:
  app                  3 files  src/app/**
  features             12 files src/features/**
  shared               8 files  src/components/**, src/hooks/**, src/lib/**, ...
  server               4 files  src/server/**

Rules:
  app features, shared, server
  features shared, server
  server shared
  shared               (isolated  no imports allowed)

Presets

The dominant React/Next.js pattern. Feature modules are isolated from each other; shared utilities and server infrastructure form the base layers.4 zones: app, features, shared, server
app       → features, shared, server
features  → shared, server
server    → shared
shared    (isolated)
The shared zone covers: components, hooks, lib, utils, utilities, providers, shared, types, styles, i18n.
This preset matches the architecture from Bulletproof React and is the most common pattern in modern React and Next.js projects.

Source root detection

Preset zone patterns use {rootDir}/{zone}/**. Fallow auto-detects the source root from tsconfig.json:
tsconfig.json
{
  "compilerOptions": {
    "rootDir": "./lib"  // zones become lib/app/**, lib/features/**, etc.
  }
}
If no rootDir is found, fallow falls back to src.

Custom zones and rules

For full control, define zones and rules directly:
{
  "boundaries": {
    "zones": [
      { "name": "ui", "patterns": ["src/components/**", "src/pages/**"] },
      { "name": "data", "patterns": ["src/db/**", "src/api/**"] },
      { "name": "shared", "patterns": ["src/lib/**", "src/utils/**"] }
    ],
    "rules": [
      { "from": "ui", "allow": ["shared"] },
      { "from": "data", "allow": ["shared"] },
      { "from": "shared", "allow": [] }
    ]
  }
}

How zones work

  • 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
  • Self-imports are always allowed (files in the same zone can freely import each other)
  • A zone with no rule entry is unrestricted: it can import from any zone
  • A zone with a rule and an empty allow list is isolated: it cannot import from other zones

Overriding preset zones

Start from a preset and customize specific zones or rules. Zones with the same name replace the preset zone; rules with the same from replace the preset rule.
{
  "boundaries": {
    "preset": "hexagonal",
    "zones": [
      { "name": "domain", "patterns": ["src/core/**"] }
    ]
  }
}
This keeps adapters and ports from the hexagonal preset but replaces the domain zone pattern with src/core/**.

Suppressing violations

Suppress individual findings with inline comments:
// fallow-ignore-next-line boundary-violation
import { db } from '../data/client';
Or suppress all boundary violations in a file:
// fallow-ignore-file boundary-violation
To suppress boundary checking entirely, set the rule severity to off:
{
  "rules": {
    "boundary-violation": "off"
  }
}
When introducing boundaries to an existing codebase, start with "warn" severity. Fix violations incrementally, then switch to "error" once the codebase is clean.

Output formats

Boundary violations appear in all output formats:
$ fallow dead-code --boundary-violations
Boundary violations (2)

  src/features/auth/login.ts:3 src/features/billing/api.ts (features  features)
  src/components/Button.tsx:1 src/server/db/client.ts (shared  server)

Inspecting your boundaries

Use fallow list --boundaries to verify your configuration before running analysis:
# Human-readable summary
fallow list --boundaries

# JSON for scripting or MCP tools
fallow list --boundaries --format json --quiet
Fallow warns when a zone matches zero files. This usually means the glob pattern doesn’t match your directory structure. Run fallow list --boundaries to check file counts per zone.

See also

fallow dead-code

CLI reference for the dead code command, including all issue type filters.

Rules & Severity

Set boundary violations to error, warn, or off.

Inline Suppression

Suppress individual findings in source code.