| name | skill-clean-architecture |
| description | Expert in Clean Architecture + Domain-Driven Design (DDD). Enforces strict separation of layers: Domain, Application, Infrastructure, Interface. No over-engineering - only essential patterns. Every file must start with a layer documentation comment. |
| compatibility | Framework agnostic. Works with Node.js, Python, Java, PHP, etc. |
| metadata | {"author":"leifermendez","version":"2.1","tags":"clean-architecture, ddd, solid, dependency-inversion, layered-architecture"} |
Overview
This skill enforces Clean Architecture and Domain-Driven Design (DDD) principles across any codebase. When invoked, it identifies the current software architecture (or lack thereof), detects layer violations and anti-patterns, and either recommends improvements within the existing architecture or recommends the best architecture for the project's size and complexity. It applies the essential 4-layer model (Domain, Application, Infrastructure, Interface) without over-engineering.
Trigger phrases: "clean architecture", "DDD", "analyze architecture", "layer violations", "dependency rule", "refactor architecture", "identify architecture", "recommend architecture", "architecture audit".
Parameters
The agent requires access to the project's source files. Before starting, confirm:
| Input | Required | Description |
|---|
| Project source directory | Yes | The root path or src/ folder to scan |
| Framework / language | Auto-detected | Detected from package.json, file extensions, config files |
| Mode | Optional | identify (detect current arch), recommend (suggest best arch), or enforce (apply Clean Architecture patterns) |
Returns
This skill produces one or more of the following outputs depending on mode:
- Architecture Identification block: detected architecture name, confidence level (High/Medium/Low), signals found, violations detected
- Architecture Recommendation block: recommended architecture, reason tied to project traits, migration path (Week 1 → Month 2+), what to avoid
- Improvement Roadmap: risk/impact matrix of proposed changes (Quick Wins → Major Projects), prioritized by low-risk/high-impact first
- Code examples: file header templates, layer structure examples, corrected code snippets for violations found
Error Handling
| Situation | Action |
|---|
| No source files found | Ask the user to confirm the project path; check for non-standard directories |
| Architecture confidence is Low | Automatically proceed to Architecture Recommendation |
| Project is too small for Clean Architecture | Recommend Feature-based or MVC; document the anti-over-engineering guard reasoning |
| Circular dependency detected | Flag as CRITICAL violation; do not attempt to silently resolve it |
| Multiple valid architectures detected | Report all candidates with confidence levels; ask the user to confirm context |
Core Philosophy: Basic Pillars, No Over-Engineering
This skill enforces only the essential 4 layers of Clean Architecture. No complex abstractions, no unnecessary patterns, no premature optimization.
The 4 Basic Pillars (Manténlo Simple)
- Domain - Entidades y reglas de negocio puras (POJOs/POCOs)
- Application - Casos de uso simples (orquestación)
- Infrastructure - Implementaciones concretas (DB, APIs externas)
- Interface - Controllers HTTP (manejo de requests/responses)
What We DON'T Want (Over-Engineering)
❌ Abstract factories para todo
❌ Event buses complejos si no hay eventos
❌ CQRS sin necesidad de escalabilidad
❌ Unit of Work si solo hay un repositorio
❌ Mappers innecesarios (usa objetos planos)
❌ Decorators de clases solo por "extensibilidad"
❌ Services de dominio si la lógica cabe en la entidad
What We DO Want (Keep It Simple)
✅ Entidades simples con validación básica
✅ Interfaces de repositorio solo con métodos necesarios
✅ Casos de uso que orquestan (no lógica de negocio)
✅ Inyección manual (sin frameworks de DI complejos)
✅ DTOs planos (clases o interfaces simples)
✅ Un archivo por responsabilidad (nada de mega-clases)
Project Discovery
When analyzing a project, always look for source code in these common folders:
Priority search locations:
src/ - Standard source folder (Node.js, TypeScript, Java)
app/ - Common in Next.js, Rails, Django projects
lib/ - Library code (Elixir, Ruby, some Node.js)
codebase/ - Legacy or enterprise projects
packages/ - Monorepo structure
src/main/ - Java/Maven standard
src/app/ - Angular/NestJS default
If no standard folder found:
- Look for
.ts, .js, .py, .java files in root
- Check
package.json for "main" entry point
- Follow imports from entry files
Always identify the main source directory before analyzing architecture.
Architecture Identification
When a user asks to "analyze", "review", or "audit" a project, run this identification protocol before any recommendations or improvements.
Step 1 — Collect Signals
Scan the project for the following observable signals. Check folder names, file names, import statements, and inline comments.
Signal Map
| Architecture | Folder Signals | File Signals | Code Signals |
|---|
| Clean Architecture | domain/, application/, infrastructure/, interface/ | *.entity.ts, *.use-case.ts, *.repository.interface.ts, *.port.ts | LAYER: comments, interfaces in domain, no framework imports in domain |
| Hexagonal (Ports & Adapters) | ports/, adapters/, driven/, driving/ | *.port.ts, *.adapter.ts, *.in.ts, *.out.ts | Interfaces grouped as inbound/outbound ports |
| DDD (Domain-Driven Design) | bounded-contexts/, aggregates/, value-objects/, domain-events/ | *.aggregate.ts, *.value-object.ts, *.domain-event.ts | Aggregate roots, domain events, ubiquitous language |
| MVC | models/, views/, controllers/ | *.model.ts, *.controller.ts, *.view.ts | Framework decorators (@Controller, @Model), direct ORM in models |
| Feature-based / Vertical Slice | Feature folders at root (users/, orders/, payments/) each with own controller + service + model | Files grouped by feature, not by type | Self-contained modules per feature with no shared domain |
| Layered / N-tier | presentation/, business/ or services/, data/ or repositories/, common/ | *.service.ts, *.repository.ts (without domain interface) | Services call repositories directly, no port/interface inversion |
| Monolithic / No pattern | Flat root structure, all files in one folder | Mixed concerns in single files (e.g., route + DB call in same file) | Controllers calling DB directly, business logic in HTTP handlers |
Step 2 — Score & Decide
Count signals per architecture. Apply this rule:
- 3+ signals from one architecture → High confidence
- 1-2 signals from one architecture → Medium confidence
- 0 signals or signals from 3+ different architectures → Low confidence / No clear pattern
Step 3 — Detect Violations
Even when an architecture is identified, check for these cross-layer violations:
❌ Domain file imports from Infrastructure or a framework
❌ Controller calls a repository directly (skips use case)
❌ Use case contains SQL queries or ORM calls
❌ Business logic lives inside an HTTP handler
❌ Circular imports between layers
❌ Entity decorated with ORM decorators (e.g. @Entity from TypeORM in domain/)
Step 4 — Produce Output
Always output this block after running the protocol:
ARCHITECTURE DETECTED: <name or "No clear pattern">
CONFIDENCE: High | Medium | Low
SIGNALS FOUND:
✅ <signal description>
⚠️ <partial signal — present but incomplete>
VIOLATIONS:
❌ <violation found>
(none if clean)
NEXT STEP: <"See Improvement Roadmap" | "See Architecture Recommendation">
If confidence is Low or architecture is "No clear pattern", proceed immediately to ## Architecture Recommendation.
Architecture Recommendation
Triggered when: Architecture Identification returns Low confidence, no clear pattern, or the user explicitly asks for a recommendation.
Step 1 — Collect Project Traits
Before recommending, gather these traits from the codebase:
PROJECT SIZE: <file count, rough LOC>
TEAM SIZE: <solo | small (2-5) | medium (5-15) | large (15+)>
DOMAIN COMPLEXITY: <simple CRUD | moderate (some rules) | complex (many entities, invariants)>
TRAFFIC/SCALE: <internal tool | startup | scaling | enterprise>
FRAMEWORK: <Express | NestJS | Django | Rails | Spring | other>
ASYNC/EVENTS: <yes (queues, events, webhooks) | no>
MULTIPLE CONTEXTS: <yes (orders, payments, users as separate systems) | no>
Step 2 — Apply Decision Matrix
Use the first matching row (ordered from simplest to most complex):
| Condition | Recommended Architecture | Reason |
|---|
| <10 source files OR pure CRUD with no business rules | Feature-based (simple modules) | No architecture overhead needed yet. Group by feature, add structure later. |
| Small project, solo/small team, growing CRUD | MVC | Proven, low ceremony, well-documented. Every framework supports it natively. |
| Medium project, domain logic present (validations, rules, workflows) | Clean Architecture (4 layers) | Separates business rules from frameworks. Safe to evolve without rewriting. |
| Large project, multiple bounded contexts, rich domain | DDD + Hexagonal | Bounded contexts prevent coupling. Hexagonal keeps the domain testable and framework-free. |
| Event-heavy system (queues, webhooks, async flows, multiple consumers) | Event-Driven + CQRS | Commands and queries separated; events as the integration contract. |
| Independent deployable modules already needed (scaling bottlenecks proven) | Microservices | Only recommend if the team has already hit scaling limits. Never as a starting point. |
Anti-over-engineering guard: NEVER recommend Clean Architecture, DDD, or Microservices for a project with fewer than ~10 source files or a simple CRUD with no business rules. Always match the architecture to the actual complexity present, not the complexity anticipated.
Step 3 — Produce Output
RECOMMENDATION: <architecture name>
REASON: <1-2 sentences tied to the project traits detected above>
COMPLEXITY FIT: <why this architecture matches the project's current size and domain>
MIGRATION PATH:
Week 1: <lowest-risk quick win — usually reorganizing folders or extracting one layer>
Week 2-4: <first structural change — e.g. create repository interfaces, extract use cases>
Month 2+: <gradual migration — one feature or bounded context at a time>
WHAT TO AVOID: <the next architecture up the complexity ladder and why not yet>
Recommendation Examples
Example A — Small Express app, ~8 files, simple CRUD
RECOMMENDATION: Feature-based (simple modules)
REASON: The project has fewer than 10 source files and no business rules beyond basic CRUD.
No architecture overhead is warranted at this stage.
COMPLEXITY FIT: Grouping by feature (users/, products/) keeps the codebase navigable
without imposing layers that would add zero value today.
MIGRATION PATH:
Week 1: Group existing files into feature folders (users/, products/)
Week 2-4: Extract a shared lib/ for utilities and validators
Month 2+: Add a services/ layer per feature if business logic grows
WHAT TO AVOID: Clean Architecture — 4 layers for 8 files is pure ceremony.
Example B — NestJS app, ~40 files, some domain logic, team of 4
RECOMMENDATION: Clean Architecture (4 layers)
REASON: The project has growing domain logic and a small team that needs clear boundaries
to avoid coupling features to the framework.
COMPLEXITY FIT: 4 layers (Domain, Application, Infrastructure, Interface) map naturally
onto NestJS modules and prevent business rules from leaking into controllers.
MIGRATION PATH:
Week 1: Add LAYER comments to all existing files; create domain/ and application/ folders
Week 2-4: Extract repository interfaces to domain/; move use case logic out of controllers
Month 2+: Migrate remaining features one use case at a time; add tests per migration
WHAT TO AVOID: DDD + Hexagonal — no multiple bounded contexts justify the extra abstraction yet.
Improvement Roadmap (Risk/Impact Matrix)
When proposing architectural improvements, always prioritize by LOW RISK + FAST IMPACT first.
The Improvement Matrix
IMPACT
Low High
┌──────────┬──────────┐
Low │ Fill-Ins │ QUICK │
RISK │ (avoid) │ WINS ⭐ │
├──────────┼──────────┤
High │ Hard │ Major │
│ Changes │ Projects │
└──────────┴──────────┘
Priority Order (Always follow this)
1. QUICK WINS ⭐ (Do First)
Low Risk + High Impact
- Add LAYER headers to existing files
- Extract interfaces for repositories (no behavior change)
- Move DTOs to Application layer
- Simple dependency inversion (constructor injection)
- Effort: Hours to 1-2 days
- Risk: Minimal (additive, non-breaking)
2. MAJOR PROJECTS (Plan Carefully)
High Risk + High Impact
- Migrate from ActiveRecord to Repository pattern
- Extract Domain layer from anemic models
- Split monolithic use cases
- Change ORM or database technology
- Effort: Weeks
- Risk: High (requires testing, gradual migration)
3. FILL-INS (Avoid or Do Last)
Low Risk + Low Impact
- Rename variables for "consistency"
- Reformat code (prettier already does this)
- Move files between folders without semantic change
- Add comments to obvious code
- Effort: Low
- Risk: None
- Value: Minimal - skip unless blocking other work
4. HARD CHANGES (Avoid or Defer)
High Risk + Low Impact
- Rewrite working code "just because"
- Change naming conventions globally
- Refactor stable legacy code with no bugs
- Effort: High
- Risk: High
- Value: Low - avoid unless necessary
Migration Strategy Example
Week 1-2: Quick Wins
✅ Add LAYER comments to all files
✅ Create repository interfaces (implement later)
✅ Move business logic from controllers to services
Week 3-4: Setup Infrastructure
✅ Implement one repository with tests
✅ Add dependency injection container
✅ Migrate one feature end-to-end
Month 2+: Gradual Migration
🔄 Migrate remaining features one by one
🔄 Keep old code working during transition
🔄 Test after each migration
Rule of Thumb
"Never break working code to 'improve' architecture. Evolution, not revolution."
- Always leave the codebase better than you found it
- Make additive changes first (new layer alongside old)
- Migrate incrementally (one use case at a time)
- Tests are mandatory before structural changes
References
Based on principles from:
- The Clean Architecture by Robert C. Martin (Uncle Bob)
- Domain-Driven Design by Eric Evans
- Hexagonal Architecture by Alistair Cockburn
- SOLID Principles
Detailed guides and examples in the references/ folder:
Patterns (Cómo hacerlo bien)
Anti-Patterns (Qué NO hacer)
Code Style (Buenas prácticas)
Examples (Ejemplos prácticos)
Layer Documentation Rule
MANDATORY: Every file MUST start with a comment indicating its layer:
Available layer tags: Domain | Application | Infrastructure | Interface
Architecture Layers (Inside-Out)
1. DOMAIN (Center - Most Protected)
Contains:
- Entities (Aggregate Roots, Entities)
- Value Objects (immutable, validated)
- Domain Services (complex business logic spanning multiple entities)
- Repository Interfaces (ports - only definitions)
- Domain Events
Rules:
- ZERO external dependencies (no frameworks, no DB, no HTTP)
- No imports from outer layers (Application, Infrastructure, Interface)
- Pure TypeScript/JavaScript/any language - only language primitives
- Business invariants enforced here
- Immutability preferred for Value Objects
Example Structure:
src/domain/
├── entities/
│ └── user.entity.ts
├── value-objects/
│ └── email.vo.ts
├── repositories/
│ └── user.repository.interface.ts
└── services/
└── user-domain.service.ts
2. APPLICATION (Use Cases / Orchestration)
Contains:
- Use Cases (application services)
- DTOs (Data Transfer Objects - input/output)
- Ports (interfaces for external services needed by use cases)
- Application Services
Rules:
- Depends ONLY on Domain layer
- No frameworks (no Express, no Fastify, no DB drivers directly)
- Orchestrates domain entities to fulfill use cases
- Defines "ports" (interfaces) for infrastructure to implement
- Transaction management lives here
- NO business logic - only coordination logic
Example Structure:
src/application/
├── use-cases/
│ ├── create-user.use-case.ts
│ └── get-user.use-case.ts
├── dtos/
│ ├── create-user.dto.ts
│ └── user-response.dto.ts
└── ports/
├── id-generator.port.ts
└── email-service.port.ts
3. INFRASTRUCTURE (External Concerns)
Contains:
- Repository Implementations (database access)
- External Service Clients (HTTP, email, SMS, payment gateways)
- Framework Adapters (Express, Fastify, NestJS adapters)
- Database Models/ORM entities (different from Domain entities!)
- Configuration and environment handling
Rules:
- Depends on Domain AND Application layers
- Implements interfaces (ports) defined in inner layers
- Can use ANY framework, library, or external service
- Converts between DB models and Domain entities
- Handles technical details (caching, retries, connection pools)
Example Structure:
src/infrastructure/
├── database/
│ ├── prisma-user.repository.ts
│ └── models/
│ └── user.model.ts
├── services/
│ ├── sendgrid-email.service.ts
│ └── uuid-generator.service.ts
└── config/
└── database.config.ts
4. INTERFACE (Presentation / Controllers)
Contains:
- Controllers (HTTP handlers)
- Routes definitions
- Middlewares (auth, validation, logging)
- Request/Response mappers
- Input validation (DTO validation)
Rules:
- Depends on Application layer (use cases)
- NO direct access to Domain or Infrastructure
- Handles HTTP specifics (status codes, headers, JSON parsing)
- Validates and sanitizes input
- Converts HTTP requests to Application DTOs
- Returns HTTP responses (never expose domain entities directly)
Example Structure:
src/interface/
├── http/
│ ├── controllers/
│ │ └── user.controller.ts
│ ├── routes/
│ │ └── user.routes.ts
│ ├── middlewares/
│ │ └── auth.middleware.ts
│ └── validators/
│ └── user.validator.ts
└── cli/ (optional)
└── commands/
Dependency Rule (The Golden Rule)
┌─────────────────────────────────┐
│ INTERFACE │ ◄── HTTP, CLI, GUI
│ (Frameworks) │
├─────────────────────────────────┤
│ INFRASTRUCTURE │ ◄── DB, External APIs, Services
│ (Adapters) │
├─────────────────────────────────┤
│ APPLICATION │ ◄── Use Cases, Orchestration
│ (Business Flow) │
├─────────────────────────────────┤
│ DOMAIN │ ◄── Business Rules, Entities
│ (Core/Business) │
└─────────────────────────────────┘
Dependencies ALWAYS point INWARD.
- Domain knows NOTHING about other layers.
- Application knows about Domain only.
- Infrastructure knows about Domain and Application.
- Interface knows about Application only.
File Header Templates
Domain Layer
Application Layer
Infrastructure Layer
Interface Layer
Minimal Example (No Over-Engineering)
Domain
export class User {
constructor(
public readonly id: string,
public readonly email: string,
public readonly name: string
) {
if (!email.includes('@')) throw new Error('Invalid email');
}
}
export interface IUserRepository {
save(user: User): Promise<void>;
findById(id: string): Promise<User | null>;
}
Application
export class CreateUserUseCase {
constructor(
private readonly userRepo: IUserRepository,
private readonly idGenerator: IIdGenerator
) {}
async execute(input: CreateUserDTO): Promise<UserResponseDTO> {
const user = new User(
this.idGenerator.generate(),
input.email,
input.name
);
await this.userRepo.save(user);
return { id: user.id, email: user.email, name: user.name };
}
}
Infrastructure
export class PrismaUserRepository implements IUserRepository {
constructor(private readonly prisma: PrismaClient) {}
async save(user: User): Promise<void> {
await this.prisma.user.create({
data: { id: user.id, email: user.email, name: user.name }
});
}
}
Interface
export class UserController {
constructor(private readonly createUserUseCase: CreateUserUseCase) {}
async create(req: Request, res: Response) {
const dto = req.body;
const result = await this.createUserUseCase.execute(dto);
res.status(201).json(result);
}
}
Anti-Patterns to Avoid
❌ Domain entity importing an ORM decorator
❌ Use case calling a database directly (use repository interface)
❌ Controller calling repository directly (must go through use case)
❌ Business logic in controllers
❌ Infrastructure details in domain (dates, UUID generation, etc.)
❌ Circular dependencies between layers
Dependency Injection (Simple)
Use a simple composition root (DI container or manual wiring):
const prisma = new PrismaClient();
const idGenerator = new UuidGenerator();
const userRepo = new PrismaUserRepository(prisma);
const createUserUseCase = new CreateUserUseCase(userRepo, idGenerator);
const userController = new UserController(createUserUseCase);
Summary Checklist