PouryaKit

What is PouryaKit

A reusable .NET 10 foundation for modular monoliths, in which Feature code holds only business behaviour.

What it is

PouryaKit is a set of NuGet packages and dotnet new templates for applications built as a Host of Modules on .NET 10 and PostgreSQL. Each Module is a business boundary that owns its data, its rules and its public Contracts.

Inside a Module, your code is Features. A Feature supplies the aggregate, the command or query, its validator and handler, its data access and its endpoint. The Kit runs everything around it: it dispatches the Operation, validates it, owns its single commit in the Unit of Work, runs its reactions and delivers its Integration Events and Snapshots to other Modules.

The packages are grouped into Capabilities: one or a few packages each, such as Messaging, Web or File storage. A Host references the ones it uses.

The packages are MIT-licensed. The Kit's source repository is private, so a package's nuget.org page has no working source link.

Feature code never commits

The Unit of Work writes the Outbox, saves and commits, and sends what it wrote only after the commit. A handler returns its Result and leaves all of it to the Unit of Work; the structure tests refuse code that saves or commits by itself.

When to use it

Start a new .NET 10 application on the Kit when its business code should be split into Modules that each own their data, and you want the commit, the Outbox, the deliveries between Modules and the checks on your composition handled for you. One Module is a fine start: the monolith template grows into a modular monolith when a second Module arrives, and a Module can later run as a service of its own.

A Feature

The handler that renames a product in the Proving Sample. It returns a Result: an Error when the product does not exist, or what the rename returned. Nothing in it saves.

RenameProductCommandHandler.cs
internal sealed class RenameProductCommandHandler(IRepository<Product, ProductId> products)
    : CommandHandler<RenameProductCommand>
{
    public override async Task<Result> Handle(
        RenameProductCommand command,
        CancellationToken cancellationToken
    )
    {
        var product = await products.FindAsync(new ProductId(command.ProductId), cancellationToken);
        return product is null ? ProductErrors.NotFound : product.Rename(command.Name);
    }
}

Start a project

Check the prerequisites

The .NET 10 SDK and Docker; Prerequisites lists what each step needs.

Install the templates

Terminal
dotnet new install PouryaKit.Templates@0.1.0-preview.2

Run your first Host

Your first Host generates a solution, starts PostgreSQL, migrates, and calls the running Host.

What the Kit guarantees

The first rule is a structure rule: the Kit's own tests are not published, so a project writes its own structure tests to hold its code to it.

RuleStated in
Feature code never saves, commits or touches the OutboxStructure tests
A Notification Handler runs only after the commitPersistence guarantees
Every failure answers one problem responseProblem responses
There is no default ActorThe Operation Context
In a tenant-scoped Module, EF Core reads and saves keep to the Operation's tenant; plain SQL states it itselfMulti-tenancy guarantees
A declaration that cannot work fails the Host when it is builtThe Host's checks

Failure messages

The Kit refuses a mistake as early as it can, and its messages name what to change.

Next steps

On this page