leifermendez/skill-pack · Archived

skill-clean-architecture

>- 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.

First seen Apr 24, 2026

Installation

$ npx skills add leifermendez/skill-pack --skill skill-clean-architecture

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from leifermendez/skill-pack · top by installs.

npx skills add leifermendez/skill-pack

Browse all from leifermendez/skill-pack

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 5
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version2.1
CompatibilityFramework agnostic. Works with Node.js, Python, Java, PHP, etc.
More metadata
author
leifermendez
version
2.1
tags
clean-architecture, ddd, solid, dependency-inversion, layered-architecture

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 26,846 B
  • docs SUMMARY.md 281 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 33 installs

SKILL.md

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)

  1. Domain - Entidades y reglas de negocio puras (POJOs/POCOs)
  2. Application - Casos de uso simples (orquestación)
  3. Infrastructure - Implementaciones concretas (DB, APIs externas)
  4. 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:

  1. src/ - Standard source folder (Node.js, TypeScript, Java)
  2. app/ - Common in Next.js, Rails, Django projects
  3. lib/ - Library code (Elixir, Ruby, some Node.js)
  4. codebase/ - Legacy or enterprise projects
  5. packages/ - Monorepo structure
  6. src/main/ - Java/Maven standard
  7. 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)

  • [references/patterns/repository-pattern.md](references/patterns/repository-pattern.md) - Repository Pattern con interfaz en Domain
  • [references/patterns/dependency-injection-simple.md](references/patterns/dependency-injection-simple.md) - Inyección manual sin frameworks
  • [references/patterns/use-case-pattern.md](references/patterns/use-case-pattern.md) - Estructura de Use Cases

Anti-Patterns (Qué NO hacer)

  • [references/anti-patterns/anemic-domain-model.md](references/anti-patterns/anemic-domain-model.md) - Entidades sin comportamiento
  • [references/anti-patterns/infrastructure-in-domain.md](references/anti-patterns/infrastructure-in-domain.md) - Frameworks en Domain
  • [references/anti-patterns/god-use-case.md](references/anti-patterns/god-use-case.md) - Use cases gigantes
  • [references/anti-patterns/leaky-abstraction.md](references/anti-patterns/leaky-abstraction.md) - Abstracciones que filtran

Code Style (Buenas prácticas)

  • [references/code-style/early-return.md](references/code-style/early-return.md) - Guard clauses, código plano
  • [references/code-style/type-safe.md](references/code-style/type-safe.md) - TypeScript strict, no any, branded types
  • [references/code-style/jsdoc-tsdoc.md](references/code-style/jsdoc-tsdoc.md) - Documentación con JSDoc/TSDoc

Examples (Ejemplos prácticos)

  • [references/examples/](references/examples/) - Ejemplos completos de flujos

Layer Documentation Rule

MANDATORY: Every file MUST start with a comment indicating its layer:

/**
 * LAYER: Domain
 * Contains: Entities, Value Objects, Domain Services, Repository Interfaces
 * Rules: No external dependencies. Pure business logic only.
 */

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

/**
 * LAYER: Domain
 * Contains: Entities, Value Objects, Domain Services
 * Rules: No external dependencies. Pure business logic.
 */

Application Layer

/**
 * LAYER: Application
 * Contains: Use Cases, DTOs, Ports
 * Rules: Orchestrates domain. No frameworks. Defines ports.
 */

Infrastructure Layer

/**
 * LAYER: Infrastructure
 * Contains: Repository implementations, external services
 * Rules: Implements ports from Application. Can use any framework.
 */

Interface Layer

/**
 * LAYER: Interface
 * Contains: Controllers, Routes, Middlewares
 * Rules: Handles HTTP. Calls use cases only. No direct domain/infrastructure access.
 */

Minimal Example (No Over-Engineering)

Domain

// src/domain/entities/user.ts
/**
 * LAYER: Domain
 * Contains: User Entity
 * Rules: No external dependencies.
 */
export class User {
  constructor(
    public readonly id: string,
    public readonly email: string,
    public readonly name: string
  ) {
    if (!email.includes('@')) throw new Error('Invalid email');
  }
}

// src/domain/repositories/user.repo.interface.ts
/**
 * LAYER: Domain
 * Contains: Repository Interface (Port)
 * Rules: Only definition, no implementation.
 */
export interface IUserRepository {
  save(user: User): Promise<void>;
  findById(id: string): Promise<User | null>;
}

Application

// src/application/use-cases/create-user.ts
/**
 * LAYER: Application
 * Contains: Create User Use Case
 * Rules: Orchestrates domain. Depends only on domain.
 */
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

// src/infrastructure/database/prisma-user.repo.ts
/**
 * LAYER: Infrastructure
 * Contains: Prisma User Repository Implementation
 * Rules: Implements domain interface. Can use Prisma.
 */
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

// src/interface/http/controllers/user.controller.ts
/**
 * LAYER: Interface
 * Contains: User HTTP Controller
 * Rules: Handles HTTP only. Calls use cases. No direct DB access.
 */
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 decoratorUse case calling a database directly (use repository interface) ❌ Controller calling repository directly (must go through use case) ❌ Business logic in controllersInfrastructure details in domain (dates, UUID generation, etc.) ❌ Circular dependencies between layers


Dependency Injection (Simple)

Use a simple composition root (DI container or manual wiring):

// src/composition.ts
const prisma = new PrismaClient();
const idGenerator = new UuidGenerator();
const userRepo = new PrismaUserRepository(prisma);
const createUserUseCase = new CreateUserUseCase(userRepo, idGenerator);
const userController = new UserController(createUserUseCase);
// Routes receive controller

Summary Checklist

  • Every file starts with LAYER comment
  • Domain has zero external dependencies
  • Application only imports from Domain
  • Infrastructure implements Application ports
  • Interface only imports from Application
  • Dependencies point inward only
  • No business logic in controllers
  • No ORM entities in Domain
  • Repository interfaces in Domain, implementations in Infrastructure
  • Use cases orchestrate, don't contain business rules