Skip to content

Architecture

Devux follows clean architecture principles with domain-driven organization. Each endpoint is self-contained with its own layers, making the codebase predictable and maintainable.

Layers

┌─────────────────────────────────────┐
│           Controller                │  ← Receives HTTP request
├─────────────────────────────────────┤
│           Validator                 │  ← Validates input with Zod
├─────────────────────────────────────┤
│           Use-Case                  │  ← Business logic
├─────────────────────────────────────┤
│         Repos / Services            │  ← Data access & shared logic
├─────────────────────────────────────┤
│           Presenter                 │  ← Formats response
└─────────────────────────────────────┘

Each layer has a single responsibility:

LayerResponsibility
ControllerReceives request, coordinates flow, returns response
ValidatorValidates request payload against Zod schema
Use-CaseExecutes business logic, orchestrates repos/services
ReposDatabase operations with input/output validation
ServicesShared business logic across endpoints
PresenterTransforms use-case output to API response format

Project Structure

apps/backend/src/
├── domains/
│   └── customers/
│       ├── endpoints/
│       │   └── create-customer/
│       │       ├── repos/                    # Endpoint-specific repos
│       │       ├── tests/
│       │       ├── create-customer.use-case.ts
│       │       ├── create-customer.responses.ts
│       │       └── create-customer.route.config.ts
│       ├── repos/                            # Domain repos (shared)
│       └── services/                         # Domain services (shared)
├── app-services/                             # Cross-domain services
├── infrastructure/
│   └── core/                                 # Framework core
└── __internals__/                            # Generated DI setup (don't edit)
    ├── domains/
    ├── app-services/
    └── registries/

packages/shared/src/shared-app/
└── domains/
    └── customers/
        ├── customers.error-codes.ts
        ├── customers.constants.ts
        └── zod-schemas/
            ├── customers.base.zod.schema.ts
            └── create-customer/
                └── create-customer.zod.schema.ts

Component Types

Per-Endpoint Components

Each endpoint gets its own set of components, generated by the CLI:

  • Use-Case – The core business logic
  • Controller – HTTP handling (auto-generated, rarely modified)
  • Validator – Input validation (auto-generated)
  • Presenter – Response formatting (auto-generated)
  • Endpoint Repos – Database operations specific to this endpoint

Shared Components

Reusable across multiple endpoints:

  • Domain Repos – Database operations shared within a domain
  • Domain Services – Business logic shared within a domain (can have their own repos)
  • App Services – Utilities shared across all domains (global or request-scoped)

Data Flow

Request → Controller → Validator → Use-Case → Presenter → Response

                    ┌─────────────────┼─────────────────┐
                    ↓                 ↓                 ↓
              Endpoint Repos    Domain Repos    Domain Services
                    ↓                 ↓                 ↓
                Database          Database        Domain Repos

                                                   Database
  1. Controller receives the HTTP request
  2. Validator validates the payload against the Zod schema
  3. Use-Case executes business logic, calling repos and services
  4. Presenter formats the response
  5. Controller returns the HTTP response

Domain Organization

Domains group related functionality. A typical e-commerce app might have:

domains/
├── customers/        # Customer management
├── products/         # Product catalog
├── orders/           # Order processing
└── payments/         # Payment handling

Each domain is independent - endpoints in customers don't directly access products repos. Cross-domain communication happens through domain services or at the use-case level.

Why This Structure?

Predictability – Every endpoint follows the same pattern. Once you understand one, you understand all.

Testability – Each component can be tested in isolation. Use-cases don't know about HTTP. Repos don't know about business rules.

Maintainability – Changes are localized. Modifying a customer endpoint doesn't affect order endpoints.

Scalability – Add new domains without touching existing code. The CLI generates consistent structure every time.