Delivery Adapters vs App Code (Strict Clean Architecture) This document clarifies where Controllers live, why they are adapters, and how to structure them cleanly in large systems. It resolves the common confusion between: • architectural role (what something is) • physical placement (where something lives in the repo) This document is framework-agnostic in its principles and feature-based in its structure. ⸻ 1. Clean Architecture Layers (Authoritative) Clean Architecture defines roles, not folders. ENTITIES USE CASES INTERFACE ADAPTERS FRAMEWORKS & DRIVERS Everything that follows maps code to these roles. ⸻ 2. What a Controller Is (Architecturally) A Controller is an Interface Adapter. Why: • It receives external input (HTTP) • It translates that input into Use Case input • It invokes a Use Case • It performs no business logic By definition: Anything that translates between external input and the application boundary is an adapter. So: ✅ Controllers are Interface Adapters ⸻ 3. Why Controllers Do NOT Live in adapters/ Although Controllers are adapters by role, they are also: • Framework-specific • Delivery-specific • Not reusable outside their app They: • use routing decorators • depend on HTTP concepts • depend on a specific framework Therefore: Controllers belong to the delivery application, not to shared adapters. ⸻ 4. Adapter vs App — The Key Distinction Concept Meaning Adapter Architectural role (translator) App Delivery mechanism (HTTP, UI, CLI) “Adapter” answers what it does. “App” answers where it runs. Both are correct at the same time. ⸻ 5. Feature-Based Structure (Mandatory for Scale) Flat technical folders do not scale. Everything is organized by feature / bounded context. ⸻ 6. Canonical Project Structure (Strict) Root core/ # Application + Domain (pure) adapters/ # Reusable infrastructure adapters apps/ # Delivery applications ⸻ Core (Feature-Based) core/ └── racing/ ├── domain/ │ ├── entities/ │ ├── value-objects/ │ └── services/ └── application/ ├── use-cases/ ├── inputs/ ├── results/ └── ports/ ├── gateways/ └── output/ • No framework imports • No DTOs • No controllers ⸻ Reusable Adapters (Framework-Agnostic Implementations) adapters/ └── racing/ ├── persistence/ │ ├── TypeOrmRaceRepository.ts │ └── TypeOrmDriverRepository.ts ├── presentation/ │ └── presenters/ │ └── GetDashboardOverviewPresenter.ts ├── messaging/ │ └── EventPublisher.ts └── logging/ └── StructuredLogger.ts These adapters: • implement Core ports • are reusable across apps • do not depend on routing or UI ⸻ API App (Delivery Application) apps/api/ └── racing/ ├── controllers/ │ └── DashboardController.ts ├── services/ │ └── DashboardApplicationService.ts ├── dto/ │ └── DashboardOverviewResponseDto.ts └── module.ts Responsibilities: • Controllers translate HTTP → Input • Application Services orchestrate Use Case + Presenter • DTOs represent HTTP contracts • Module wires dependencies ⸻ 7. Responsibilities by Layer (No Overlap) Controllers • HTTP only • No business logic • No mapping logic • Call Application Services only Application Services (API) • Instantiate Output Adapters • Invoke Use Cases • Return response DTOs Presenters • Implement Output Ports • Map Result → DTO/ViewModel • Hold state per execution ⸻ 8. Forbidden Patterns ❌ Controllers inside adapters/ ❌ Use Cases inside apps/api ❌ DTOs inside core ❌ Controllers calling Use Cases directly ❌ Business logic in Controllers or Services ⸻ 9. Final Mental Model Controllers are adapters by responsibility. Apps define where adapters live. This separation allows: • strict Clean Architecture • multiple delivery mechanisms • feature-level scalability ⸻ 10. One-Line Summary Controller = Adapter (role), App = Delivery (location). This document is the authoritative reference for controller placement and adapter roles.