Use Official Presets
Official presets encode best practices. Start with one that matches your architecture.
The .stricture/config.json file is where you define your architecture rules. This file controls how Stricture enforces boundaries in your codebase.
Stricture supports two configuration approaches:
Configure directly in your ESLint config:
import stricture from '@stricture/eslint-plugin'
export default [ stricture.configs.hexagonal({ ignorePatterns: ['**/*.test.ts'], // ... custom config })]Use inline when:
Use .stricture/config.json for complex setups:
{ "preset": "@stricture/hexagonal", "boundaries": [ /* many boundaries */ ], "rules": [ /* many rules */ ]}export default [ stricture.configs.recommended()]Use file-based when:
Both approaches are equally valid - choose what works best for your team.
Place your configuration at the root of your project:
my-project/├── .stricture/│ └── config.json # Your Stricture configuration├── src/├── package.json└── ...Stricture automatically discovers this file when running ESLint.
Here’s the complete configuration schema with all available options:
interface StrictureConfig { version?: string // Config version (default: '1') preset: string // Base preset to use extends?: string[] // Additional presets to merge boundaries: BoundaryDefinition[] // Boundary definitions rules: ArchRule[] // Architecture rules overrides?: Partial<ArchRule>[] // Override preset rules ignorePatterns?: string[] // Global ignore patterns metadata?: Record<string, unknown> // Custom metadata}The simplest configuration uses a preset with no customizations:
{ "preset": "@stricture/hexagonal"}{ "preset": "@stricture/layered"}{ "preset": "@stricture/clean"}{ "preset": "@stricture/nextjs"}Add custom boundaries while keeping preset rules:
{ "preset": "@stricture/hexagonal", "boundaries": [ { "name": "shared", "pattern": "src/shared/**", "mode": "file", "tags": ["shared"], "metadata": { "description": "Shared utilities accessible from all layers" } } ], "rules": [ { "id": "all-to-shared", "name": "All Layers Can Use Shared", "description": "Shared utilities are accessible everywhere", "severity": "error", "from": { "pattern": "**" }, "to": { "tag": "shared" }, "allowed": true } ]}Your custom boundaries and rules are merged with the preset’s definitions.
Override specific preset rules:
{ "preset": "@stricture/hexagonal", "overrides": [ { "id": "domain-isolation", "severity": "warn" // Change from error to warning }, { "id": "driving-independent", "severity": "off" // Disable this rule } ]}Build your architecture from scratch:
{ "boundaries": [ { "name": "controllers", "pattern": "src/controllers/**", "mode": "file", "tags": ["presentation"] }, { "name": "services", "pattern": "src/services/**", "mode": "file", "tags": ["business"] }, { "name": "repositories", "pattern": "src/repositories/**", "mode": "file", "tags": ["data"] } ], "rules": [ { "id": "controllers-to-services", "name": "Controllers Call Services", "description": "Presentation layer uses business layer", "severity": "error", "from": { "tag": "presentation" }, "to": { "tag": "business" }, "allowed": true }, { "id": "services-to-repositories", "name": "Services Use Repositories", "description": "Business layer uses data layer", "severity": "error", "from": { "tag": "business" }, "to": { "tag": "data" }, "allowed": true }, { "id": "no-upward-deps", "name": "No Upward Dependencies", "description": "Lower layers cannot depend on higher layers", "severity": "error", "from": { "tag": "data" }, "to": { "tag": "business" }, "allowed": false, "message": "Data layer cannot import from business layer" } ]}Compose multiple presets:
{ "preset": "@stricture/hexagonal", "extends": [ "@company/shared-rules", "@company/security-rules" ]}Presets are merged in order:
preset)extends array, in order)Exclude files from architecture validation:
{ "preset": "@stricture/hexagonal", "ignorePatterns": [ "**/*.test.ts", "**/*.spec.ts", "**/mocks/**", "**/test-utils/**", "**/__tests__/**" ]}Common patterns to ignore:
versionType: string (optional)
Default: "1"
Configuration schema version. Reserved for future breaking changes.
{ "version": "1", "preset": "@stricture/hexagonal"}presetType: string
Required
The base architecture preset to use. See available presets.
{ "preset": "@stricture/hexagonal"}Available official presets:
@stricture/hexagonal - Ports & Adapters@stricture/layered - N-Tier Architecture@stricture/clean - Clean Architecture@stricture/modular - Feature Modules@stricture/nextjs - Next.js App Router@stricture/nestjs - NestJS ModulesextendsType: string[] (optional)
Additional presets to merge. Useful for:
{ "preset": "@stricture/hexagonal", "extends": [ "@mycompany/architecture-standards", "@mycompany/security-rules" ]}boundariesType: BoundaryDefinition[]
Define architectural boundaries. See Boundaries Reference.
{ "boundaries": [ { "name": "domain", "pattern": "src/domain/**", "mode": "file", "tags": ["domain"] } ]}rulesType: ArchRule[]
Define architecture enforcement rules. See Rules Reference.
{ "rules": [ { "id": "domain-isolation", "name": "Domain Isolation", "description": "Domain must be pure", "severity": "error", "from": { "tag": "domain" }, "to": { "tag": "*" }, "allowed": false } ]}overridesType: Partial<ArchRule>[] (optional)
Override specific rules from presets. Only include properties you want to change:
{ "preset": "@stricture/hexagonal", "overrides": [ { "id": "domain-isolation", "severity": "warn", "message": "Custom warning message" } ]}Common override scenarios:
error → warn → off)ignorePatternsType: string[] (optional)
Glob patterns for files to exclude from validation:
{ "ignorePatterns": [ "**/*.test.ts", "**/*.spec.ts", "**/generated/**", "**/__mocks__/**" ]}metadataType: Record<string, unknown> (optional)
Custom metadata for documentation or tooling:
{ "preset": "@stricture/hexagonal", "metadata": { "author": "Architecture Team", "lastReview": "2024-01-15", "documentation": "https://wiki.company.com/architecture", }}For type-safety and IntelliSense, you can use TypeScript instead of JSON:
import type { StrictureConfig } from '@stricture/core'
export default { preset: '@stricture/hexagonal', boundaries: [ { name: 'shared', pattern: 'src/shared/**', mode: 'file', tags: ['shared'] } ], rules: [ { id: 'all-to-shared', name: 'All Can Use Shared', description: 'Shared utilities accessible everywhere', severity: 'error', from: { pattern: '**' }, to: { tag: 'shared' }, allowed: true } ]} satisfies StrictureConfigStricture validates your configuration on load. Common validation errors:
{ "boundaries": [ { "name": "domain" // ❌ Missing: pattern, mode } ]}Error: BoundaryDefinition must have 'pattern' and 'mode' properties
{ "rules": [ { "severity": "critical" // ❌ Invalid value } ]}Error: Severity must be 'error', 'warn', or 'off'
{ "boundaries": [ { "name": "domain", "pattern": "src/domain/[invalid", // ❌ Malformed glob "mode": "file" } ]}Error: Invalid glob pattern: unclosed bracket
{ "preset": "@stricture/hexagonal", "boundaries": [ { "name": "shared-kernel", "pattern": "packages/shared/**", "mode": "file", "tags": ["shared"] }, { "name": "package-a-domain", "pattern": "packages/package-a/src/domain/**", "mode": "file", "tags": ["domain", "package-a"] }, { "name": "package-b-domain", "pattern": "packages/package-b/src/domain/**", "mode": "file", "tags": ["domain", "package-b"] } ], "rules": [ { "id": "all-to-shared-kernel", "from": { "pattern": "**" }, "to": { "tag": "shared" }, "allowed": true }, { "id": "packages-isolated", "name": "Packages Are Isolated", "description": "package-a cannot import package-b", "severity": "error", "from": { "tag": "package-a" }, "to": { "tag": "package-b" }, "allowed": false, "message": "Packages must be independent. Use shared-kernel for common code." } ]}{ "preset": "@stricture/nextjs", "boundaries": [ { "name": "server-components", "pattern": "app/**/page.tsx", "mode": "file", "tags": ["server", "react"] }, { "name": "client-components", "pattern": "app/**/*.client.tsx", "mode": "file", "tags": ["client", "react"] }, { "name": "server-actions", "pattern": "app/**/actions.ts", "mode": "file", "tags": ["server", "actions"] } ], "rules": [ { "id": "server-components-no-client-only", "name": "Server Components Cannot Use Client-Only Code", "severity": "error", "from": { "tag": "server" }, "to": { "pattern": "node_modules/{react-dom/client,zustand}/**" }, "allowed": false, "message": "Server Components cannot use client-only packages. Mark component with 'use client' directive." } ]}Use Official Presets
Official presets encode best practices. Start with one that matches your architecture.
// ✅ GOOD - Simple and clear{ "preset": "@stricture/hexagonal"}
// ❌ AVOID - Over-engineered{ "preset": "@stricture/hexagonal", "boundaries": [ /* 20+ custom boundaries */ ], "rules": [ /* 50+ custom rules */ ]}{ "rules": [ { "id": "legacy-isolation", "name": "Legacy Code Isolated", "description": "TEMPORARY: Legacy code in src/legacy/ cannot be imported by new code. Will be removed in Q3 2024.", "severity": "error", "from": { "pattern": "src/**", "exclude": ["src/legacy/**"] }, "to": { "pattern": "src/legacy/**" }, "allowed": false, "message": "Don't depend on legacy code. Refactor or duplicate needed logic." } ]}Commit .stricture/config.json to version control:
# ✅ Include Stricture config.stricture/config.json
# ❌ Don't ignore itWhen adding to existing codebase:
{ "preset": "@stricture/hexagonal", "overrides": [ // Start with warnings { "id": "domain-isolation", "severity": "warn" } ], "ignorePatterns": [ // Exclude legacy code "src/legacy/**" ]}Gradually tighten rules as you refactor.
Minimum setup:
npm install -D @stricture/eslint-pluginThen create a custom config in .stricture/config.json.
Recommended setup (with preset):
npm install -D @stricture/eslint-pluginThen reference a bundled preset:
{ "preset": "@stricture/hexagonal"}Can I use multiple presets?
Yes, use the extends field:
{ "preset": "@stricture/hexagonal", "extends": ["@stricture/nextjs"]}Error: Could not find .stricture/config.json
Solution: Create .stricture/config.json at project root (where package.json is).
Error: Could not resolve preset '@stricture/hexagonal'
Solution: Install the preset package:
pnpm add -D @stricture/hexagonalProblem: ESLint not reporting violations
Checklist:
.eslintrc.js with @stricture plugin)ignorePatterns?Run with debug logging:
DEBUG=stricture:* eslint src/Problem: Rules seem to contradict each other
Solution: Check rule specificity. More specific rules override general ones. See Rules Reference.
Boundaries Reference
Learn how to define architectural boundaries.
Rules Reference
Master architecture enforcement rules.
Presets Reference
Explore and extend presets.