Architecture enforcement for React and TypeScript projects.
ArchGuard is a local-first CLI that checks layer boundaries, flags a small set of structural UI violations, and fails fast in local development or CI when code breaks the configured architecture.
ArchGuard is intended for teams that:
- use React and TypeScript
- organize code into explicit layers such as
domain,features, andui - want deterministic architectural checks instead of review-only enforcement
This is not a general-purpose static analysis framework. The current implementation is deliberately narrow and opinionated.
ArchGuard is aimed at teams that want architecture enforcement without introducing a test DSL or a large analysis framework.
- CLI-first: it runs as a direct command in local development, pre-commit hooks, and CI.
- Deterministic: it uses explicit layer rules from
architecture.yamlinstead of inference-heavy heuristics for boundaries. - Incremental rollout: baseline mode lets teams adopt the tool without stopping work to clean all historical violations first.
- Contributor guidance included:
initgeneratesAGENTS.mdand.archguard/ARCHITECTURE_RULES.mdfrom the same source of truth.
The tradeoff is deliberate: smaller surface area, faster setup, and less configurability than broad architecture-testing libraries.
- Layer Boundary Enforcement: Blocks imports that violate configured layer rules.
- Component Logic Checks: Flags loops and similar logic patterns inside React components.
- UI Data Access Checks: Flags direct data fetching inside UI components.
- Cycle Detection: Detects circular dependencies across local imports the resolver can map.
- Baseline Mode: Supports incremental rollout by suppressing already-known violations.
- Structured Output: Emits
jsonandsariffor CI wrappers and code-scanning workflows. - Path Alias Resolution: Resolves relative imports and common
tsconfig.jsonaliases before rule evaluation.
The repository root remains private because it also hosts the GitHub Action and the monorepo workspace setup. The publishable CLI is the @archguard/cli workspace package.
Use the npm install path only after you have verified that the published package name and scope point to this repository's release.
npm install --save-dev @archguard/cli
npx archguard initIf npx archguard does not resolve after installation, the installed registry package is not exposing the
expected archguard binary. In that case, verify the published package metadata before using the npm path.
Publishing these packages under their current names requires control of the @archguard npm scope.
If you are evaluating the project from source before installing from npm, use the local link workflow:
npm install
npm run build
npm linkAfter linking, the archguard command is available in other local projects on the same machine.
For release validation before publishing the workspace packages:
npm run release:checkTo publish the workspace packages in dependency order after authenticating with npm:
npm run release:publishA step-by-step release checklist is included in PUBLISHING.md.
archguard initThis command:
- verifies that the target project looks like a React + TypeScript repository
- writes
architecture.yaml - writes
AGENTS.mdif the file does not already exist - writes
.archguard/ARCHITECTURE_RULES.md - installs a pre-commit hook only if no existing hook is present
archguard checkarchguard check --update-baseline
archguard check --baseline--update-baseline writes .archguard-baseline.json. Later runs with --baseline suppress matching historical violations and fail only on new ones.
ArchGuard reads architecture.yaml from the current working directory or the nearest parent directory.
layers:
domain:
allowedImports: []
features:
allowedImports: [domain, shared]
ui:
allowedImports: [features, shared]
rules:
noBusinessLogicInComponents: true
noDataFetchingInUI: true
enforceFeatureBoundaries: true
noCircularLayerDeps: trueAvailable preset:
feature-sliced-react
archguard initarchguard init --preset feature-sliced-reactarchguard checkarchguard check --format json
archguard check --format sarifarchguard check --baseline
archguard check --update-baselineThis repository includes a composite GitHub Action that installs and runs ArchGuard in the checked-out repository.
- uses: actions/checkout@v4
- uses: lindseystead/ArchGuard@v1
with:
format: json- uses: actions/checkout@v4
- uses: lindseystead/ArchGuard@v1
with:
format: json
working-directory: apps/web- uses: actions/checkout@v4
- id: archguard
continue-on-error: true
uses: lindseystead/ArchGuard@v1
with:
format: sarif
output-file: reports/archguard.sarif
- if: ${{ always() }}
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: reports/archguard.sarif
- if: ${{ steps.archguard.outcome == 'failure' }}
run: exit 1archguard/
├── packages/
│ ├── core/ # Shared types, config loading, parsing, and resolution helpers
│ ├── cli/ # Command-line entry point and reporting
│ ├── rules-react/ # React-specific rule implementations
│ └── guidance/ # Project guidance document generator
└── architecture.schema.ts
A passing example project is included in examples/react-layered-app. It shows the intended folder layout and a minimal code path that satisfies the default layered rules.
ArchGuard uses the TypeScript compiler API to parse .ts and .tsx files.
At a high level:
- import declarations are extracted from the AST
- file paths are mapped to layers by matching configured folder names
- relative imports and common
tsconfig.jsonpath aliases are resolved to build an import graph - React component checks inspect component AST nodes for loops, complex conditionals, and known fetch calls
The AGENTS.md and .archguard/ARCHITECTURE_RULES.md files are generated reference documents for contributors and supporting tooling. They are not the source of truth and they are not the enforcement mechanism. Enforcement happens in the CLI through architecture.yaml.
- component behavior checks are heuristic-based rather than semantically complete
- layer detection depends on directory names matching configured layer names
- advanced TypeScript project references and non-standard workspace resolution are not fully supported yet
- circular dependency detection is limited to imports the CLI can resolve to local files
- the default pre-commit integration installs only when no hook already exists
These are explicit product constraints, not hidden behavior.
Run the full suite from the repository root:
npm testAll workspace packages now run real tests as part of the root suite. The root test command is the expected verification step before pushing changes.
MIT. See LICENSE.