Forge combines three architectural paradigms — Hexagonal Architecture, Pragmatic Domain-Driven Design, and Vertical Slices — into a single enforced discipline. Each paradigm addresses a different axis of complexity: Hexagonal Architecture isolates business logic from technical infrastructure, Pragmatic DDD structures business logic around bounded contexts and rich domain models, and Vertical Slices ensure those bounded contexts own their full stack from HTTP to persistence. Together they produce systems where every component has a single, auditable owner, cross-feature coupling is structurally impossible, and infrastructure can be swapped without touching business logic.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ronaldjdev/forge/llms.txt
Use this file to discover all available pages before exploring further.
Hexagonal Architecture (Ports & Adapters)
Hexagonal Architecture draws a hard boundary between the domain (business rules) and everything outside it (frameworks, databases, external services). The domain expresses its needs through ports — interfaces declared in the domain layer. The outside world satisfies those needs through adapters — concrete implementations that live at the edge of the system. In Forge, this maps directly to directory structure:| Hexagonal Concept | Forge Location | Example |
|---|---|---|
| Domain | features/<name>/domain/ | User.entity.ts, IUser.repository.ts |
| Inbound adapter (HTTP) | features/<name>/adapters/in/http/ | User.controller.ts, User.routes.ts |
| Outbound adapter (persistence) | features/<name>/adapters/out/persistence/ | User.repository.ts, User.schema.ts |
| Port (repository interface) | features/<name>/domain/ | IUser.repository.ts |
domain → infra prohibited) and R6 (domain → platform prohibited) protect the port boundary. R1 (feature → infra prohibited) ensures features go through infra/ adapters rather than calling the ORM directly.
Pragmatic DDD
Domain-Driven Design provides vocabulary and structure for modeling complex business domains: entities (objects with identity and state), use cases (application-level orchestration of domain operations), repositories (domain interfaces to persistence), and domain events (notifications of state changes). Forge adopts these patterns pragmatically — meaning they are applied where they add clarity, not where they add ceremony. In Forge, each feature is a bounded context with its own domain, application, and adapter layers:Entities
Entities
Entities carry identity (an
id field) and domain invariants. They are plain TypeScript classes with a static create() factory method — no ORM decorators, no framework imports. The entity knows nothing about how it is persisted.Use Cases
Use Cases
Use cases orchestrate domain operations. A use case receives typed inputs, calls domain methods, delegates persistence to a repository interface, and returns domain objects. They contain the only place where business rules are enforced. Controllers never contain business logic.
Repository Interfaces (Ports)
Repository Interfaces (Ports)
Repository interfaces live in
domain/ and declare the persistence contract in domain terms (findById, save, findByEmail). The implementation lives in adapters/out/persistence/ and translates between domain objects and ORM records.Domain Events
Domain Events
Events are named in the past tense (
UserCreated, OrderPaid) and represent facts that have occurred in the domain. They are raised by use cases and consumed by event handlers that may live in other features — without direct cross-feature imports.string is often better than a ValueObject<Email>. A direct method call is often better than a DomainEvent. Add DDD scaffolding when the domain logic demands it, not to satisfy a pattern checklist.
Vertical Slices
Vertical Slices organize code by business capability rather than by technical layer. Instead of acontrollers/ folder containing all controllers, a services/ folder containing all services, and a repositories/ folder containing all repositories, each feature owns all of its layers from top to bottom.
In Forge, every src/features/<name>/ directory is a complete vertical slice:
payments feature can evolve it — change the domain model, swap the database adapter, add a new use case — without touching any other feature directory. Cross-feature coupling is prohibited by rule (R8: cross-feature direct imports = ERROR), so the only sanctioned communication channel between features is injection via interfaces.
The Four Layers as System-Level Separation
Within the vertical slice model, Forge adds four horizontal layers that handle concerns that span all features:| Layer | Purpose | Examples |
|---|---|---|
| Platform | Technical backbone shared by all features | config/, database/, http/, server/, logger/, di/, security/ |
| Features | Vertical business slices | users/, orders/, payments/ |
| Shared | Pure horizontal utilities with no business or infrastructure knowledge | errors/, contracts/, types/, utils/ |
| Infra | Concrete implementations of ports | prisma/, mongodb/, redis/, mail/ |
Principle Summary
| Principle | Enforced By | Key Rule |
|---|---|---|
| Domain isolation | quench | R5 (domain → infra), R6 (domain → platform) |
| No cross-feature coupling | quench | R8 (cross-feature direct imports) |
| Infrastructure at the edge | quench | R1 (feature → infra), R7 (infra → feature) |
| Platform stays technical | quench | R2 (platform → feature), R13 (domain artifacts in platform) |
| Shared stays pure | quench | R3 (shared → feature), R4 (shared → infra) |
| Dependency direction | quench | R9 (dependency cycles) |
| Zero business logic in controllers | inspect | Decorators category |
| DI by constructor only | temper | Decorators + DI strategy validation |
These principles are not optional style guidelines — they are the basis for the 13 dependency rules that
quench enforces automatically on every file change. Violations are reported with CRITICAL, ERROR, or WARNING severity and can block commits via the git pre-commit hook (forge hook install).