Pure business rules, with no dependency on frameworks, databases or third-party libraries.
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.
Depends only on the domain. Holds use cases, DTOs and the contracts it needs.
Implements those contracts with EF Core and Dapper.
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.
| Operation | Tool | Why |
|---|---|---|
| Domain mutations | EF Core 10 | Change tracking, aggregate lifecycle and schema migrations, with transactional safety and no partial updates. |
| High-throughput queries | Dapper | No 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.
| Verb | Path | Description |
|---|---|---|
GET | /api/v1/health | Service health check. |
GET | /api/v1/work-items | List items, optionally filtered by ?status=, read through Dapper. |
GET | /api/v1/work-items/{id} | Get one item. |
POST | /api/v1/work-items | Create an item through EF Core. |
PUT | /api/v1/work-items/{id} | Update title, description and priority. |
PATCH | /api/v1/work-items/{id}/status | Move 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.