Skip to main content

Built-in Templates

Ten templates ship as embedded YAML resources, all in schema 2.

Every layer of a standalone template has an id with a pack prefix (CA- for clean-architecture, ONION-, HEX-, LAY-, MS-, ED-, VS- and MM- for the others, as in CA-LAYER-DOMAIN), a because written for that architecture, and a namespace selector of the form **.<Segment>.**. Domain in clean-architecture is **.Domain.**, which matches Shop.Domain and Shop.Orders.Domain.Entities. A solution whose namespaces do not follow that naming retargets the layers; see Rule Schema. None of the built-in packs defines rules yet.

The templates fall into two categories:

Standalone Templates​

Standalone templates define their own layers and can be used independently.

clean-architecture​

4 layers, 19 roles. The classic Clean Architecture pattern (Robert C. Martin).

LayerDependenciesRoles
Domain(none)Entity, ValueObject, DomainService, DomainServiceInterface, DomainEvent, Specification, RepositoryInterface
ApplicationDomainCommandHandler, CommandHandlerInterface, QueryHandler, QueryHandlerInterface, Dto, Mapper, Validator, ExternalServiceInterface
InfrastructureDomain, ApplicationRepository (internal), ExternalService (internal)
WebApiDomain, Application, InfrastructureController, Middleware

onion-architecture​

5 layers, 14 roles. Onion Architecture (Jeffrey Palermo).

LayerDependenciesKey Roles
DomainModel(none)Entity, ValueObject, DomainEnum
DomainServicesDomainModelRepositoryInterface, DomainServiceInterface, DomainEvent
ApplicationServicesDomainModel, DomainServicesApplicationService, ApplicationServiceInterface, Dto
InfrastructureDomainModel, DomainServices, ApplicationServicesRepository (internal), DomainService (internal), DbContext
PresentationDomainModel, DomainServices, ApplicationServicesController, ViewModel

hexagonal-architecture​

3 layers, 7 roles. Ports & Adapters pattern (Alistair Cockburn).

LayerDependenciesKey Roles
Core(none)Entity, ValueObject, DomainService
PortsCoreDrivingPort (Interface), DrivenPort (Interface)
AdaptersCore, PortsPrimaryAdapter, SecondaryAdapter (internal)

layered​

3 layers, 11 roles. Traditional N-tier / layered architecture.

LayerDependenciesKey Roles
PresentationBusinessController, ViewModel, ApiModel
BusinessDataAccessService, ServiceInterface, Validator, BusinessModel
DataAccess(none)Repository, RepositoryInterface, DbContext, DataModel

Note: dependency direction is top-down (Presentation → Business → DataAccess), unlike Clean Architecture where it flows inward.

microservice​

5 layers, 17 roles. Per-service microservice structure.

LayerDependenciesKey Roles
Domain(none)Entity, Aggregate, ValueObject, DomainEvent, RepositoryInterface
ApplicationDomain, ContractsHandler, ApplicationService, ApplicationServiceInterface
InfrastructureDomain, Application, ContractsRepository (internal), DbContext, MessagePublisher, MessageConsumer
ApiDomain, Application, ContractsController, GrpcService
Contracts(none)IntegrationEvent, ApiRequest, ApiResponse

Note: Contracts is a leaf layer with no dependencies — it contains shared DTOs and integration events that other services can consume.

event-driven​

5 layers, 9 roles. Event-driven architecture.

LayerDependenciesKey Roles
Domain(none)(inherits from composed packs)
EventsDomainEvent, IntegrationEvent
ProducersDomain, EventsEventProducer, EventProducerInterface
ConsumersDomain, EventsEventConsumer, EventConsumerInterface, EventHandler
InfrastructureDomain, Events, Producers, ConsumersMessageBrokerAdapter (internal), MessageBrokerInterface

vertical-slice​

3 layers, 8 roles. Vertical slice / feature-based architecture.

LayerDependenciesKey Roles
Feature(none)Request, Response, Handler, Validator, Endpoint
SharedKernel(none)SharedEntity, SharedDto
InfrastructureFeature, SharedKernelDbContext

modular-monolith​

4 layers, 8 roles. Modular monolith pattern.

LayerDependenciesKey Roles
Module.Public(none)ModuleContract (Interface), ModuleEvent, ModuleDto
Module.CoreModule.PublicModuleService (internal), ModuleEntity, ModuleRepositoryInterface
Module.InfrastructureModule.Public, Module.CoreModuleRepository (internal)
HostModule.Public, Module.Core, Module.InfrastructureModuleRegistration

The layers select **.Public.**, **.Core.**, **.Infrastructure.** and **.Host.**, so Orders.Core and Billing.Core are one layer, and Orders.Core may depend on Billing.Core. The pack does not isolate modules from each other. A rule type for module isolation is tracked in issue #32.

Composable Add-on Templates​

Add-on templates define only component roles (no layers). They are designed to be composed with standalone templates via the extends field. Only role-only add-ons compose with a layer pack: two templates that both define layers fail to compose.

cqrs​

7 roles. Command/Query Responsibility Segregation.

RoleLayerTypeKind
CommandApplicationRecord
CommandHandlerApplicationClass (requires interface)
CommandHandlerInterfaceApplicationInterface
QueryApplicationRecord
QueryHandlerApplicationClass (requires interface)
QueryHandlerInterfaceApplicationInterface
QueryResultApplicationRecord

Usage: extends: [builtin://clean-architecture, builtin://cqrs]

ddd-tactical​

9 roles. Domain-Driven Design tactical patterns.

RoleLayerTypeKind
AggregateDomainClass
AggregateRootDomainClass
ValueObjectDomainRecord
DomainEventDomainRecord
DomainServiceDomainClass (requires interface)
DomainServiceInterfaceDomainInterface
SpecificationDomainClass
FactoryDomainClass
DomainExceptionDomainClass

Usage: extends: [builtin://clean-architecture, builtin://ddd-tactical]

Composing Templates​

Templates compose via the merge described in Rule Engine. A layer or rule can be defined by one pack only, so exactly one standalone template can be the base, and the add-ons come on top of it:

# .architecture/rules.yaml
schema: 2
name: my-project
extends:
- builtin://clean-architecture # base: 4 layers, 19 roles
- builtin://cqrs # add-on: +7 roles
- builtin://ddd-tactical # add-on: +9 roles (some overlap)

# Team-specific additions
componentRoles:
- name: OutboxMessage
layer: Infrastructure
typeKind: Class

Naming two standalone templates fails the load. clean-architecture+microservice gives, for each layer both define, a message such as packs 'clean-architecture' and 'microservice' both define layer 'Domain'. Pick one base architecture and retarget its layers instead.

The cqrs and ddd-tactical roles name the Application and Domain layers but declare no layers of their own. They resolve on their own, but combine them with a base pack that declares those layers; once the merged pack has any layer, a role naming an undeclared layer is an Invalid error. Composing ddd-tactical with a base pack that has no Domain layer, such as hexagonal-architecture, fails for that reason.

The resolved pack will have:

  • Name: "clean-architecture+cqrs+ddd-tactical+my-project"
  • Layers: 4 (from clean-architecture, unmodified since add-ons define no layers)
  • Roles: ~30 (19 + 7 + 9, minus overlaps where later packs override)
  • Rules: none, because no built-in pack defines rules yet