First Project
This guide walks through setting up Anvil in an existing TypeScript project with intentional architecture boundaries.
Scenario
You have a project with this structure:
my-app/
├── src/
│ ├── api/ # HTTP handlers
│ ├── services/ # Business logic
│ ├── repositories/ # Data access
│ └── utils/ # Shared utilities
├── package.json
└── tsconfig.json
You want to enforce these boundaries:
api/can import fromservices/but notrepositories/services/can import fromrepositories/andutils/repositories/can only import fromutils/utils/cannot import from other layers
Step 1: Install and Initialise
pnpm add -D @eddacraft/anvil-cli
anvil init
Step 2: Define Architecture Boundaries
Edit anvil.config.json to add boundary rules:
{
"version": "1.0",
"gates": {
"architecture": {
"enabled": true,
"boundaries": [
{
"name": "api-layer",
"pattern": "src/api/**",
"allow": ["src/services/**", "src/utils/**"],
"deny": ["src/repositories/**"]
},
{
"name": "service-layer",
"pattern": "src/services/**",
"allow": ["src/repositories/**", "src/utils/**"],
"deny": ["src/api/**"]
},
{
"name": "repository-layer",
"pattern": "src/repositories/**",
"allow": ["src/utils/**"],
"deny": ["src/api/**", "src/services/**"]
},
{
"name": "utils",
"pattern": "src/utils/**",
"allow": [],
"deny": ["src/api/**", "src/services/**", "src/repositories/**"]
}
]
},
"antiPatterns": {
"enabled": true,
"patterns": ["AP-001", "AP-003", "AP-004", "AP-006"]
}
}
}
Step 3: Run Initial Check
anvil run
You might see existing violations:
🔨 Anvil Run
Checking architecture...
✗ ARCH-001: Boundary violation
src/api/handlers/user.ts imports from src/repositories/user.repo.ts
Rule: api-layer denies imports from src/repositories/**
Checking anti-patterns...
⚠️ AP-003: Explicit 'any' type
src/services/parser.ts:42:10
1 error, 1 warning found.
Gate status: FAIL
Step 4: Fix Violations
For architecture violations, you have two options:
Option A: Fix the Code
Refactor to respect boundaries. In the example above, the API handler should call a service, not a repository directly:
// Before (violation)
import { UserRepo } from '../repositories/user.repo';
// After (correct)
import { UserService } from '../services/user.service';
Option B: Suppress with Explanation
If the violation is intentional, add a suppression:
// @anvil-ignore ARCH-001 Legacy pattern, will refactor in Q2
import { UserRepo } from '../repositories/user.repo';
@anvil-ignore without a reasonwill itself trigger a warning. :::
Step 5: Start Watch Mode
Once clean (or suppressions added), start watch mode:
anvil watch
Now any new violations will surface immediately when you save.
Step 6: Add to CI
Add Anvil to your CI pipeline:
# .github/workflows/ci.yml
- name: Run Anvil
run: pnpm anvil run --ci
The --ci flag produces machine-readable output and sets appropriate exit
codes.
What You've Achieved
- Anvil validates architecture boundaries on every save
- New boundary violations are caught before commit
- Anti-patterns surface immediately
- CI blocks PRs with violations