Skip to content

ADR-004: Solution Structure

Status: Accepted Date: 2026-02-07

Context

The project spans 4 development phases, involves multiple contributors, and has complex cross-cutting concerns (permissions, auditing). The team needed a solution structure that supports long-term maintainability without excessive boilerplate.

Decision

Modular monolith - Clean Architecture project boundaries with feature-based vertical slices as separate projects.

Rationale

This is a hybrid of Clean Architecture and Vertical Slices:

  • Clean Architecture boundaries provide strict dependency rules (Domain has no dependencies, Infrastructure is swappable)
  • Feature projects provide isolation so each domain area (Projects, Timelines, Characters, Factions, Collaboration) owns its entities, logic, endpoints, and tests
  • Shared projects (Domain, Infrastructure, Common) provide the boilerplate foundation so features don't duplicate base classes, DbContext, auth, or utility code

Benefits for this project specifically:

  • Different developers can own different feature projects without merge conflicts
  • Phase 2 (Characters/Factions) means adding new projects, not modifying Phase 1 code
  • Each feature is independently testable
  • Complex features (like Relationships with its permission logic) stay contained
  • Shared permission logic lives in Common, reusable across all features

Alternatives Considered

  • Pure Clean Architecture - Domain, Application, Infrastructure, API as four projects. Feature code organized by folders within Application. Rejected because the team wanted stronger feature isolation than folders provide
  • Pure Vertical Slices - Single project with feature folders. Fast to build but shared concerns (permissions, auditing) get duplicated or awkwardly placed. Rejected for long-term maintainability concerns with 4 phases of development
  • Simple layered - Single project with Controllers/Services/Models folders. Rejected as likely to become messy by Phase 2-3 given the number of entities and complex permission logic

Structure

src/
├── Shared/
│   ├── KnowledgeBase.Domain/
│   ├── KnowledgeBase.Infrastructure/
│   └── KnowledgeBase.Common/
├── Features/
│   ├── KnowledgeBase.Projects/
│   ├── KnowledgeBase.Timelines/
│   ├── KnowledgeBase.Characters/
│   ├── KnowledgeBase.Factions/
│   └── KnowledgeBase.Collaboration/
└── KnowledgeBase.API/

Consequences

  • More projects in the solution means more project references to manage
  • Feature projects reference shared projects but should minimize cross-feature references
  • Need clear guidelines on what belongs in shared vs. feature-specific code
  • DbContext configuration may need to discover entity configurations across multiple feature projects