MaxSud.ModularMonolith.Templates
1.1.0
dotnet new install MaxSud.ModularMonolith.Templates@1.1.0
MaxSud.ModularMonolith.Templates
Production-grade dotnet new templates for a .NET 10 Modular Monolith built on
Clean Architecture, DDD and CQRS — the architecture, not a demo of it.
dotnet new install MaxSud.ModularMonolith.Templates
dotnet new modmono -n Acme.Shop
cd Acme.Shop
docker compose up -d # Postgres · Redis · RabbitMQ · MinIO · Mailpit · Flarex
Swagger lands on http://localhost:5050/api-docs, health on /health/ready.
What you get
| Modular monolith | Every module owns its DbContext, its PostgreSQL schema and its migration history. Modules never call each other synchronously — they talk over integration events. |
| Clean Architecture | Domain → Application → Infrastructure / Presentation per module, enforced at build time by NetArchTest architecture tests. |
| CQRS without MediatR | A small in-process IDispatcher backed by DI, with a five-stage pipeline: Logging → Metrics → Validation → Concurrency → UnitOfWork → handler. No third-party licence to track. |
| Transactional outbox | Domain events → outbox rows written in the same transaction as the business change → Quartz processor → RabbitMQ integration events. At-least-once, retry-counted, poison-message-capped. |
| Result, not exceptions | Result / Result<T> / Error with an error category that maps to RFC 9457 ProblemDetails. Exceptions stay reserved for genuine faults. |
| Auth & RBAC | JWT access + refresh tokens, device sessions with revoke, email verification, password reset & change, optional 2FA, and permission-based authorization (RequireAuthorization("users:write") — no policy registration needed). |
| Docs enforced by the compiler | TreatWarningsAsErrors is on and CS1591 is not suppressed: an undocumented public member fails dotnet build. The generated code ships fully documented and stays that way. |
| Tests included | xUnit unit tests, Testcontainers-backed integration tests, and NetArchTest architecture tests that fail the build if a layer reaches the wrong way. |
| Observability | Serilog → console/file/Flarex (a self-hosted log dashboard on Seq's ingestion protocol, in the compose stack at http://localhost:5341), OpenTelemetry traces + metrics ready to export over OTLP, correlation-id middleware, three readiness health checks. |
Templates in this pack
| Short name | Creates |
|---|---|
modmono |
The full solution — API host, Common layers, Users module, optional Catalog sample module, tests, Docker stack. |
modmono-module |
A new module inside an existing solution: five projects, DbContext + schema, unit of work, outbox job, registration extensions — and it splices itself into Api.csproj and ServiceCollectionExtensions.cs. |
modmono-feature |
One vertical slice (command or query + handler + validator + endpoint) inside an existing module. |
Options — dotnet new modmono
| Option | Default | Effect when false |
|---|---|---|
--use-redis |
true |
ICacheService falls back to an in-memory implementation; no Redis dependency. |
--use-rabbitmq |
true |
Outbox, integration events and the *.IntegrationEvents projects are removed. Domain events still dispatch in-process. |
--use-quartz |
true |
No background jobs. Forced back on when --use-rabbitmq is on (the outbox processor is a Quartz job). |
--use-storage |
true |
No S3/MinIO IFileStorage, no presigned uploads, no avatar endpoint. |
--use-signalr |
true |
No hubs, no realtime notifier, no Redis backplane. |
--use-email |
true |
No SMTP sender; email verification, password reset and 2FA flows are removed with it. |
--use-otel |
true |
No OpenTelemetry wiring and no MetricsBehavior in the pipeline. |
--use-localization |
true |
Errors return their English description; no Accept-Language middleware. |
--use-swagger |
true |
No Swashbuckle, no /api-docs. |
--sample-module |
true |
The Catalog demo module is not generated. |
--tests |
true |
No test projects. |
--docker |
true |
No Dockerfile, compose files or .env.example. |
Migrations are not part of the pack: which columns exist depends on the options you chose, so a pre-baked migration would be wrong for most combinations. Generate them once, right after creating the project:
./scripts/init-migrations.sh # or init-migrations.ps1 on Windows
Examples:
# Everything on (recommended starting point)
dotnet new modmono -n Acme.Shop
# Lean HTTP API: no bus, no realtime, no object storage, no sample module
dotnet new modmono -n Acme.Lite \
--use-rabbitmq false --use-signalr false --use-storage false --sample-module false
# Add a module to the solution you just made
cd Acme.Shop
dotnet new modmono-module -n Orders
# Add a vertical slice to it
dotnet new modmono-feature -n PlaceOrder --module Orders --kind command
Prefer to be asked rather than to remember flags? scripts/new-app.ps1 (or new-app.sh)
walks through the options interactively and calls dotnet new for you.
Requirements
- .NET SDK 10.0.100 or newer
- Docker (for
docker compose upand for the generated integration tests, which start a throwaway PostgreSQL container through Testcontainers)
Working on the templates themselves
src/MaxSud.ModularMonolith.Templates/templates/solution/ is a real, buildable
solution, not an inert blob of text. Conditional regions are guarded by a hidden
TemplateAuthoring symbol that defines every feature constant when you build the
folder directly, and disappears when the template is instantiated. So you edit and
debug the template the same way you'd edit any application.
./scripts/pack.ps1 # pack + install the local build over any released one
dotnet test ./tests/TemplateTests # generate + build every option combination
See docs/AUTHORING.md for the full loop, the conditional syntax per
file type, and how releases are cut.
Licence
MIT — see LICENSE.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.