template-dotnet-clean-arch
Starter template · .NET 10 · Vue 3 · MIT

A .NET and Vue starter with the layers already drawn.

A working work-item tracker that shows where each kind of code goes: business rules in the domain, writes through EF Core, reads through Dapper, and a typed Vue client on top. Fork it and replace the example with your own domain.

  • .NET 10 Web API
  • EF Core 10 + Dapper
  • Vue 3 + TypeScript
  • PostgreSQL 16 or SQLite

Four layers, dependencies point inward

Infrastructure implements the contracts that the domain and application layers own. Nothing in the domain knows about a database or a web framework.

Clean Architecture layers of the .NET template Presentation calls Application, which depends on Domain. Infrastructure sits to the side and implements the contracts owned by Application and Domain. Presentation Vue 3 SPA · ASP.NET Core controllers · ProblemDetails Application WorkItemService · DTOs · read contract Domain WorkItem aggregate · repository contract · domain errors Infrastructure EF Core 10 · writes Dapper · reads PostgreSQL / SQLite implements implements
Domain

Pure business rules, with no dependency on frameworks, databases or third-party libraries.

Application

Depends only on the domain. Holds use cases, DTOs and the contracts it needs.

Infrastructure

Implements those contracts with EF Core and Dapper.

Presentation

ASP.NET Core controllers and the Vue 3 single-page application.

EF Core for writes, Dapper for reads

Each tool does the job it is best at, behind separate contracts.

OperationToolWhy
Domain mutationsEF Core 10Change tracking, aggregate lifecycle and schema migrations, with transactional safety and no partial updates.
High-throughput queriesDapperNo object-tracking overhead, explicit parameterised SQL and simple mapping for lists and dashboards.

Run it in a minute

Local development falls back to SQLite, so you need no database. Docker Compose runs the full stack on PostgreSQL 16.

Local, with SQLite

cd backend
dotnet run --project src/Presentation/Template.Api/Template.Api.csproj
# API on http://localhost:5000

cd frontend
npm install
npm run dev
# client on http://localhost:5173

Docker Compose, with PostgreSQL

docker compose up --build
# client   http://localhost:8080
# API      http://localhost:5000
# Postgres localhost:5432

Verify

dotnet test backend/template-dotnet-clean-arch.slnx
cd frontend && npm run build

The example API

Errors use RFC 7807 ProblemDetails. The OpenAPI document is served at /openapi/v1.json.

VerbPathDescription
GET/api/v1/healthService health check.
GET/api/v1/work-itemsList items, optionally filtered by ?status=, read through Dapper.
GET/api/v1/work-items/{id}Get one item.
POST/api/v1/work-itemsCreate an item through EF Core.
PUT/api/v1/work-items/{id}Update title, description and priority.
PATCH/api/v1/work-items/{id}/statusMove an item to another status.
DELETE/api/v1/work-items/{id}Delete an item.

Every pull request runs the backend tests and the frontend build through the shared reusable workflows in the NainDev organisation.