# VerticalSliceArchitecture: a .NET 10 template built around features

> This learning template organises a .NET 10 API by feature rather than by layer, so a booking or cancellation is a single file holding its endpoint, command, validator and handler, over a clinic scheduling domain. It is a teaching artefact with a dev container and Swagger on port 5206, not a framework you depend on.

**nadirbad/VerticalSliceArchitecture** — Vertical Slice Architecture solution template in .NET 10

- Repository: https://github.com/nadirbad/VerticalSliceArchitecture
- Website: https://nadirbad.dev/vertical-slice-architecture-dotnet
- Stars: 605 · Forks: 100
- Language: C#
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/nadirbad-verticalslicearchitecture

## Layers versus features, drawn side by side

The README opens with the definition it exists to demonstrate. Instead of organizing code by technical layers, Controllers, Services and Repositories, Vertical Slice Architecture organizes code by features, and each feature contains everything it needs, endpoint, validation, business logic and data access, all in one place.

The comparison the README draws makes the difference concrete. A layered project puts an AppointmentsController in one directory, an AppointmentService in another, an AppointmentRepository in a third and the Appointment model in a fourth, while the vertical layout puts BookAppointment.cs, CancelAppointment.cs, CompleteAppointment.cs and GetAppointments.cs in a Features folder, with the domain types in their own Domain folder alongside.

The stated benefits follow from that arrangement rather than from any tooling. You can change one feature without touching others. There is no jumping between layers, because everything is co-located. It is easier to understand, test and maintain, and features can evolve independently.

The subjects of this project are the domain objects, and the pattern is about where the code that touches them lives. The repository is a template for a specific way of organising a .NET service, and the rest of the README is a tour of what that looks like when a real set of rules is pushed through it.

## A clinic booking domain, because the rules are the point

The template models a medical clinic appointment scheduling system where patients book appointments with doctors, and the README is explicit that the domain enforces real-world constraints.

Three of them are named. Doctors cannot be double-booked. Appointments must be scheduled in advance. And the appointment lifecycle transitions are controlled, with scheduled appointments able to be completed or cancelled, and those two being terminal states.

That choice of domain is the pedagogical decision in the project. A feature-sliced example built around a to-do list would show the file layout and nothing else, because there would be no rules to distribute across the slices. A clinic booking has exactly the kind of constraints that make the layout earn its keep: the double-booking check is business logic, the advance notice is validation, the terminal states are domain rules, and the endpoint has to refuse the request cleanly.

It is also why the errors are modelled rather than thrown. The five endpoints in the table all return errors for specific reasons, and the code uses a result type to carry them, so the interesting part of the example, a rejection with a reason attached, is visible in the signature of the handler.

The domain is small enough to read in an afternoon, which is the point of a learning template.

## Five endpoints, and the rules attached to each

The Features and Business Rules table is the specification of the example, and each row reads like a test case.

Book Appointment is `POST /api/appointments`, and its key rules are no double-booking doctors, 15 minutes of advance notice and a duration between 10 minutes and 8 hours. Get Appointments is `GET /api/appointments`, which can filter by patient, doctor, status and date range and is paginated with a maximum of 100 results. Get by ID is `GET /api/appointments/{id}` and returns the full appointment with patient and doctor details.

The two state transitions are the interesting rows. Complete is `POST /api/appointments/{id}/complete`, which cannot complete a cancelled appointment and is idempotent. Cancel is `POST /api/appointments/{id}/cancel`, which cannot cancel a completed appointment, requires a reason and is idempotent.

Those two rows are where the architecture pays for itself. A double-booking check needs the schedule, so the query lives next to the command that needs it. An idempotent cancel needs to know what state the appointment is in, and that knowledge sits in the same slice. In a layered layout those rules end up in a service that both endpoints call, which is exactly the coupling the slice layout is meant to remove.

The idempotency requirement is also a real design constraint rather than decoration, since a retried request after a timeout must not fail.

## One file holds the endpoint, the command, the validator and the handler

The Feature Anatomy section opens by saying that each feature file contains everything needed for that operation, and then shows the parts.

The command is a record with a typed result:

```csharp
// 2. Command (Request)
public record BookAppointmentCommand(
    Guid PatientId, Guid DoctorId,
    DateTimeOffset Start, DateTimeOffset End,
    string? Notes) : IRequest<ErrorOr<BookAppointmentResult>>;

// 3. Validator
internal sealed class BookAppointmentCommandValidator : AbstractValidator<BookAppointmentCommand>
{
    public BookAppointmentCommandValidator()
    {
        RuleFor(v => v.PatientId).NotEmpty();
        RuleFor(v => v.DoctorId).NotEmpty();
        RuleFor(v => v.Start).Must(BeInFuture).WithMessage("Must book at least 15 minutes in advance");
        // ... more rules
    }
}
```

Two details are worth naming. The advance-notice rule is expressed in the validator rather than in the handler, which means a request that fails it is rejected before any database work happens. And the command's result type is an either-or of a success and a list of errors, so a handler that finds a double booking returns errors rather than throwing.

The project structure diagram shows the same shape at directory level, with the Scheduling folder holding BookAppointment.cs, CancelAppointment.cs, CompleteAppointment.cs, GetAppointments.cs and GetAppointmentById.cs, each described as a command, validator, handler and endpoint, next to a Domain folder with a rich domain model of Appointment, Patient and Doctor plus an Events folder, a Common folder with a validation filter and a problem helper, and an Infrastructure folder with the database context.

## Three commands to a running API on port 5206

The Quick Start section is deliberately short, and it assumes a .NET 10 SDK and a reachable PostgreSQL.

```bash
# Clone and run
git clone https://github.com/nadirbad/VerticalSliceArchitecture.git
cd VerticalSliceArchitecture
dotnet run --project src/Api/Api.csproj

# Open Swagger UI
open http://localhost:5206
```

The API project is `src/Api/Api.csproj`, and the entry point is a single Program.cs described as the minimal hosting setup, which is the .NET 10 minimal APIs style. Once it is running, the Swagger UI is the way to exercise the five endpoints, and the port is 5206.

The repository root shows the rest of the scaffolding: a `VerticalSliceArchitecture.slnx` solution, a global.json pinning the SDK, Directory.Build.props and Directory.Packages.props for shared build settings and central package versions, a `requests` directory, a `tests` directory, and a .devcontainer directory.

The technologies are the other half of the example. The API is built on .NET 10 Minimal APIs, which the table describes as a lightweight HTTP endpoint approach on an LTS release. MediatR provides the request and response pattern and the pipeline behaviours, FluentValidation the declarative validation rules, ErrorOr the result pattern for error handling, and Entity Framework Core the persistence. The README also links a Complete Guide to Vertical Slice Architecture and a Quick Start Guide on the same site, plus a GitHub Codespaces badge for a browser-based environment.

## The dev container brings its own PostgreSQL 16

The Dev Container and Codespaces section is the part that decides whether you can try the template today.

The claim is that the fastest way to get a fully working environment with PostgreSQL requires no local setup. In GitHub Codespaces, the environment is ready with .NET 10, PostgreSQL, EF tools and all the VS Code extensions pre-configured. In a local VS Code Dev Container, the README lists what happens automatically: it installs the .NET 10 SDK and EF Core tools, starts PostgreSQL 16 with the database pre-created, restores packages, builds and applies the migrations, and forwards ports for the Swagger UI and for database access.

The database configuration is in a docker-compose file at the root, and it is a single service:

```yaml
services:
  postgres:
    image: postgres:16-alpine
    container_name: vsa-postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=yourStrong(!)Password
      - POSTGRES_DB=VerticalSliceDb
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
```

So PostgreSQL 16 on Alpine, a named volume for the data directory, port 5432 published, and a healthcheck that asks the server whether it is ready to accept connections. The password is a placeholder in the compose file, which is the right thing for a template and also a reminder that it is not a deployment configuration.

## A learning template, released as a repository rather than a package

It is worth being clear about what this project is, because the repository name and the topic list could suggest something more general. The README calls it a learning template demonstrating Vertical Slice Architecture with a healthcare appointment scheduling domain, and the topics confirm the scope: vertical-slice-architecture, vertical-slices, minimal-api, clean-architecture, software-architecture, and a run of dotnet version tags from 6 to 10.

There is no package to install and no library to reference. The deliverable is the source tree, and the audience is a developer who wants to read one complete implementation of an idea.

The licence is MIT, with the LICENSE file at the repository root, which means you can copy the tree into your own project and adapt it freely, and the author's own site carries the long-form guide that the README points to.

The repository is not archived, and the last push was on 2026-08-09, with no GitHub releases, so the state of the template is the state of the main branch. For a template that is the right arrangement, since the value is in reading the code rather than consuming a version. The two things to be careful about are that the pattern is only as good as the discipline that keeps it, and that the example is a clinic with five endpoints, which is a good teaching size and a very small production system.

## Conclusion

VerticalSliceArchitecture fits a developer who wants to see vertical slice architecture applied to a domain with real rules, and who learns best by reading a complete worked example rather than a reference library. It is the wrong starting point for a production service, because it is explicitly a learning template with a single shared database and a small domain, and it is the wrong choice if you want MediatR-free code. Verify first that the .NET 10 SDK and PostgreSQL are available to you, that the port 5206 is free, and that the vertical slicing style is one your team already has the discipline to keep.

## FAQ

### What is VerticalSliceArchitecture?

It is a .NET 10 learning template demonstrating Vertical Slice Architecture with a healthcare appointment scheduling domain. Instead of organizing code by technical layers such as Controllers, Services and Repositories, it organizes code by features, with each feature holding its endpoint, validation, business logic and data access together.

### How do I run the VerticalSliceArchitecture template locally?

Clone the repository, change into the directory and run dotnet run --project src/Api/Api.csproj, then open http://localhost:5206 for the Swagger UI. The README also documents a dev container that installs the .NET 10 SDK and EF Core tools, starts PostgreSQL 16 with the database pre-created, applies the migrations and forwards the ports.

### What business rules does the appointment domain enforce?

Doctors cannot be double-booked, appointments must be booked at least 15 minutes in advance and last between 10 minutes and 8 hours, and completed or cancelled appointments are terminal states, so a cancelled appointment cannot be completed and a completed one cannot be cancelled.

### What is inside a feature slice file?

The endpoint handler, the command with its validator, and the handler carrying the business logic. The project structure places five such files, BookAppointment.cs, CancelAppointment.cs, CompleteAppointment.cs, GetAppointments.cs and GetAppointmentById.cs, in the Scheduling folder, next to the domain entities and a shared Common folder.

### Which libraries does the template use?

The technologies table lists .NET 10 Minimal APIs for the endpoints, MediatR for the request and response pattern and pipeline behaviours, FluentValidation for declarative validation rules, ErrorOr as the result pattern for error handling, and Entity Framework Core for persistence. The database is PostgreSQL 16 on Alpine, configured in docker-compose.yml.

## Sources

- [Issues](https://github.com/nadirbad/VerticalSliceArchitecture/issues)
- [License: MIT](https://github.com/nadirbad/VerticalSliceArchitecture/blob/main/LICENSE)
- [nadirbad/VerticalSliceArchitecture on GitHub](https://github.com/nadirbad/VerticalSliceArchitecture)
- [Project website](https://nadirbad.dev/vertical-slice-architecture-dotnet)
- [README](https://github.com/nadirbad/VerticalSliceArchitecture/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nadirbad-verticalslicearchitecture
