Architecture¶
High‑level view¶
The Cargonerds solution is built on top of the ABP Framework and uses a layered architecture. At the heart of the system lies the domain model and business logic. Around the domain layer are several projects that serve specific purposes: defining interfaces and DTOs, hosting application services, integrating with Entity Framework Core, exposing HTTP APIs and serving the user interface【405741767768697†L799-L846】. Each of these projects resides in its own assembly and references only the layers it requires, ensuring a clear separation of concerns.
While ABP defines how the application code is structured, .NET Aspire
provides a unified way to run and observe all services. Aspire is described
as an “opinionated, cloud‑ready stack” for building distributed applications
with built‑in support for observability and resource modelling【798564215460282†L254-L259】.
In this solution, the Cargonerds.AppHost project uses Aspire to declare
resources such as SQL Server, Redis and RabbitMQ and to orchestrate the
services that make up the application (AuthServer, HttpApi.Host,
Web.Public, Blazor, NpmApp and DbMigrator). When run locally the AppHost
spins up these resources (as Docker containers by default) and configures
environment variables so that the services can find each other. When
deployed to Azure, Aspire works with the Azure Developer CLI (azd) to
provision equivalents such as Azure SQL, Azure Cache for Redis and Azure
Container Apps.
The diagram below illustrates this high‑level structure. The services are grouped into three tiers: the orchestrator (AppHost) at the top, the application services in the middle and the infrastructure resources at the bottom. Solid arrows indicate primary dependencies (for example the AuthServer, HttpApi.Host, Web.Public and DbMigrator all depend on the database). Dashed and dotted arrows indicate ancillary connections such as frontend clients calling the API or services authenticating against the AuthServer. Redis and RabbitMQ are optional caches/messaging systems used by the services and are therefore not wired explicitly in the diagram.

Layered architecture¶
ABP divides each module into a set of well‑defined layers. The main layers
are summarised below. These descriptions are generic; they apply to both
the main Cargonerds module and the Hub module.
.Domain.Shared project¶
This project contains constants, enums and simple types that belong to the
domain but need to be shared with other layers. Since these values are
used across the solution, every other project depends on .Domain.Shared but
.Domain.Shared itself has no dependencies【405741767768697†L799-L808】.
.Domain project¶
The domain layer is the heart of the application. It contains
entities, aggregate roots, domain services, value objects and
repository interfaces【405741767768697†L810-L819】. Domain services encapsulate complex business
rules that cannot naturally be placed in entities. The domain project
depends only on .Domain.Shared so that it can reuse shared constants and
enumerations.
.Application.Contracts project¶
This project defines the application service interfaces and the Data Transfer Objects (DTOs) used to communicate with clients. It separates the contract from the implementation, which allows the interfaces and DTOs to be shared with client applications without exposing the implementation details【405741767768697†L822-L833】.
.Application project¶
The application layer contains the concrete implementations of the
application service interfaces. Application services orchestrate domain
objects and enforce business rules by invoking domain services and
repositories. This project depends on .Application.Contracts and the
.Domain project because it needs to implement the contracts using domain
objects【405741767768697†L836-L846】.
.EntityFrameworkCore project¶
This is the data access layer when using Entity Framework Core as the
persistence provider. It defines the DbContext and implements repository
interfaces defined in the domain layer【405741767768697†L848-L855】. The project depends
on .Domain because it maps domain entities to database tables and
implements repository methods.
.DbMigrator project¶
The DbMigrator is a console application used to create the database,
apply migrations and seed initial data【405741767768697†L859-L884】. It is designed for
both development and production: run it whenever you add a new migration
or deploy to a fresh environment. The migrator depends on
.EntityFrameworkCore to access migrations and on .Application.Contracts
to grant permissions while seeding data【405741767768697†L881-L885】.
.HttpApi project¶
This project contains API controllers. ABP automatically generates API
controllers for most application services, but you can manually create
controllers here when needed【405741767768697†L887-L898】. It depends on
.Application.Contracts so that controllers can call the application
services.
.HttpApi.Client project¶
In some scenarios you may want to consume your APIs from a .NET client.
The .HttpApi.Client project defines C# client proxies for your HTTP
APIs【405741767768697†L899-L914】. You can reference this package from other .NET
applications to call your own APIs without manually writing HTTP clients.
.UI projects¶
The user interface is implemented in two ways in this solution:
- Web.Public – an ASP.NET Core MVC/Razor Pages application that
provides the public web site. It references the
.HttpApilayer to consume APIs and defines Razor pages, JavaScript and CSS resources【405741767768697†L919-L929】. In a tiered deployment the UI does not reference.Applicationor.EntityFrameworkCore, even though those references appear in the project file; they are only needed when the application is not deployed in a tiered manner【405741767768697†L931-L941】. - Blazor – a client‑side Blazor WebAssembly application. It
references the
.HttpApi.Clientproject to call the backend and uses ABP’s Blazor UI libraries. There is also aCargonerds.Blazor.Clientproject which hosts the client code when running in ASP.NET Core.
In addition to these UI projects, there is a NpmApp under the AppHost which runs a Node‑based front‑end (for instance an Next.js application). The Npm app communicates with the backend through the HttpApi host and authenticates via the AuthServer.
Summary¶
The layered architecture ensures that responsibilities are clearly separated: business rules reside in the domain layer, application services orchestrate those rules, data access is isolated behind repositories, and presentation layers consume the APIs. .NET Aspire unifies the orchestration and deployment of these layers, making it easy to run the entire system on your development machine or in the cloud. For practical steps on how to run and deploy the system, see the Deployment guide.