MinimalCleanArch.Templates
0.1.18
dotnet new install MinimalCleanArch.Templates::0.1.18
MinimalCleanArch Templates
Project templates for bootstrapping Clean Architecture APIs with MinimalCleanArch, using vertical-slice-style use-case organization inside clean dependency boundaries.
Quick Start
Default multi-project app (SQLite):
dotnet new install MinimalCleanArch.Templates
dotnet new mca -n MyApp
cd MyApp
dotnet run --project src/MyApp.Api
Recommended single-project app:
dotnet new mca -n MyApp --single-project --recommended
cd MyApp
dotnet run
Open Scalar at https://localhost:<port>/scalar/v1.
What It Builds
- a Minimal API application that starts with MCA package boundaries already in place instead of leaving architecture decisions implicit
- either a layered multi-project solution or a pragmatic single-project application with the same conceptual separation
- an application where domain, application, infrastructure, and host concerns already follow the intended dependency direction
- optional capabilities such as auth, audit logging, messaging, caching, telemetry, and deployment scripts without hand-assembling the baseline
Choosing a Shape
- Default multi-project template: best when you want strict project boundaries and independent domain/application/infrastructure assemblies.
--single-project: best when you want the same architectural separation but lower solution complexity and faster iteration for smaller services.--recommended: good default for production-oriented APIs that need HTTP polish and operational basics without every optional subsystem.--all: good for exploring the full MCA stack, generated tests, and deployment workflows end to end.
Install
From NuGet:
dotnet new install MinimalCleanArch.Templates
From local packages:
dotnet new uninstall MinimalCleanArch.Templates
dotnet new install ./artifacts/packages
Common Examples
# Default multi-project app
dotnet new mca -n OrderService
# Production-ready API
dotnet new mca -n OrderService --recommended --db sqlserver --docker
# Full-featured app
dotnet new mca -n EnterpriseApp --all --db postgres --tests
# Secure API
dotnet new mca -n SecureApp --auth --db postgres
# Public API with rate limiting
dotnet new mca -n PublicApi --single-project --ratelimiting
For template flags, architecture details, auth notes, and deployment workflows, use the sections below after choosing a starting point.
What Gets Scaffolded
Multi-project (default):
MyApp/
|- MyApp.slnx
|- src/
| |- MyApp.Domain/
| |- MyApp.Application/
| |- MyApp.Infrastructure/
| |- MyApp.Api/
|- tests/
|- Dockerfile
|- docker-compose.yml
Single project:
MyApp/
|- MyApp.csproj
|- Program.cs
|- Domain/
|- Application/
|- Infrastructure/
|- Endpoints/
Try Auth + Scalar Password Flow (5 Minutes)
This is the quickest way to validate OpenIddict + user auth + global Bearer reuse in Scalar.
- Scaffold and run:
dotnet new mca -n QuickAuth --single-project --auth --tests --mcaVersion 0.1.18
cd QuickAuth
dotnet run
Open
https://localhost:<port>/scalar/v1.Register a user with
POST /api/auth/register:
{
"email": "demo@example.com",
"password": "TempPass!123",
"firstName": "Demo",
"lastName": "User"
}
- Click
Authorizein Scalar and use the preconfiguredoauth2password flow:
- Username:
demo@example.com - Password:
TempPass!123
- Call an authenticated endpoint, for example
POST /api/auth/change-password:
{
"currentPassword": "TempPass!123",
"newPassword": "TempPass!456"
}
- Optional: inspect claims with
GET /connect/userinfo.
Notes:
- In Development, Scalar is preconfigured with OAuth2 password flow (
/connect/token) and a preferredoauth2security scheme. - The bearer token is persisted and automatically reused for secured requests.
Try Password Reset Email Quickly (SMTP or API)
- Configure
EmailSettingsinappsettings.json(or user-secrets):
Provider(SmtporApi)SenderEmailAppBaseUrl- SMTP mode:
SmtpServer,Port,EnableSsl, credentials if needed - API mode:
Api:Endpoint, optionalApi:ApiKey,Api:ApiKeyHeaderName,Api:ApiKeyPrefix,Api:Headers
- Example API-mode configuration:
{
"EmailSettings": {
"Provider": "Api",
"SenderEmail": "no-reply@example.com",
"SenderName": "MCA",
"AppBaseUrl": "https://localhost:5001",
"Api": {
"Endpoint": "https://your-email-api.example.com/send",
"ApiKey": "your-api-key",
"ApiKeyHeaderName": "Authorization",
"ApiKeyPrefix": "Bearer",
"Headers": {
"X-Tenant": "demo"
}
}
}
}
The API sender posts JSON in this shape:
{
"from": { "email": "no-reply@example.com", "name": "MCA" },
"to": [{ "email": "user@example.com" }],
"subject": "Subject",
"html": "<p>Body</p>",
"text": "Body"
}
- Trigger reset flow:
POST /api/auth/forgot-passwordwith an email.- Response intentionally does not include reset token.
Use your email provider/local SMTP capture to obtain the link/token.
Complete reset via
POST /api/auth/reset-password.
Try Durable Messaging (Outbox) Quickly
Use SQL Server or PostgreSQL (SQLite is in-memory messaging only).
- Start DB container:
SQL Server:
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=StrongP!12asd" -p 1433:1433 --name sqlserver -d mcr.microsoft.com/mssql/server:2022-latest
PostgreSQL:
docker run -e "POSTGRES_USER=postgres" -e "POSTGRES_PASSWORD=postgres" -e "POSTGRES_DB=mca" -p 5432:5432 --name postgres -d postgres:16-alpine
- Scaffold with messaging + DB provider:
dotnet new mca -n DurableApp --all --db postgres --tests
Deployment Scripts (Generated App)
When you scaffold with --docker (or --all), the generated app includes scripts/ for local deployment workflows.
Recommended default: Docker Compose
PowerShell:
pwsh ./scripts/deploy.ps1 -Target compose
pwsh ./scripts/compose-down.ps1 -RemoveVolumes
Bash:
./scripts/deploy.sh --target compose
./scripts/compose-down.sh --remove-volumes
Optional local Kubernetes smoke path (kind):
PowerShell:
pwsh ./scripts/deploy.ps1 -Target kind -ImageTag myapp:local
Bash:
./scripts/deploy.sh --target kind --image-tag myapp:local
Notes:
- Compose is the fastest way to validate full local dependencies (API + DB + cache from
docker-compose.yml). - The kind smoke path is best for quick API image validation and local cluster checks.
- For SQL Server/PostgreSQL generated apps, prefer Compose unless you also deploy matching DB services to your cluster.
- Compose uses
name: ${COMPOSE_PROJECT_NAME:-mca}; the generated compose scripts automatically setCOMPOSE_PROJECT_NAMEfrom the app folder name. You can override it explicitly withCOMPOSE_PROJECT_NAME=....
Template Options
Presets
| Option | Description |
|---|---|
--recommended |
Includes: serilog, healthchecks, validation, security, caching, ratelimiting |
--all |
Includes: auth, messaging, audit, opentelemetry, docker, tests (plus recommended set) |
Project Structure
| Option | Default | Description |
|---|---|---|
--single-project |
false | Single project instead of multi-project solution |
--tests |
false | Include test projects |
--docker |
false | Include Dockerfile and docker-compose.yml |
How Options Affect Architecture
| Option | Main effect on generated solution |
|---|---|
--single-project |
Collapses layers into one project while keeping Domain, Application, Infrastructure, and endpoint folders separate by responsibility |
--tests |
Adds unit and integration test projects or test targets for the generated app |
--docker |
Adds container build and local deployment assets (Dockerfile, docker-compose.yml, generated scripts/) |
--recommended |
Enables common API-facing concerns such as logging, validation, health checks, security, caching, and rate limiting |
--all |
Builds on --recommended and adds auth, messaging, audit, telemetry, tests, and deployment assets |
Features
| Option | Description |
|---|---|
--serilog |
Structured logging with Serilog |
--healthchecks |
Health check endpoints |
--validation |
FluentValidation integration |
--auth |
OpenIddict auth (Identity + OAuth2/OIDC) |
--security |
Encryption, security headers, CORS |
--caching |
In-memory and Redis caching |
--ratelimiting |
Global + endpoint-specific rate limiting with 429 ProblemDetails |
--messaging |
Wolverine domain events |
--audit |
Audit logging |
--opentelemetry |
Distributed tracing |
Feature-to-Layer Impact
| Feature | Generated layers most affected | What changes |
|---|---|---|
--validation |
Application, Api |
Adds validators plus API-side validation registration |
--auth |
Infrastructure, Api |
Adds Identity/OpenIddict persistence, auth endpoints, and security setup |
--security |
Infrastructure, Api |
Adds encryption/security registrations and HTTP security defaults |
--caching |
Infrastructure, Api |
Adds cache configuration and host wiring |
--messaging |
Application, Infrastructure, Api |
Adds domain-event handlers/contracts plus Wolverine setup and transport wiring |
--audit |
Infrastructure, Api |
Adds audit persistence, interception, and registration |
--opentelemetry |
Api |
Adds tracing/telemetry host configuration |
--docker |
solution root / host assets | Adds container and deployment workflow assets, not domain rules |
Database
| Option | Default | Description |
|---|---|---|
--db sqlite |
Yes | SQLite |
--db sqlserver |
SQL Server | |
--db postgres |
PostgreSQL | |
--dbName <name> |
MCA_DB | Database name for generated connection strings/compose settings |
Versions
| Option | Default | Description |
|---|---|---|
--mcaVersion <version> |
0.1.18 | MinimalCleanArch package version |
--framework <tfm> |
net10.0 | Target framework (net9.0 or net10.0) |
Architecture Overview
Generated apps follow a hybrid approach: Clean Architecture for dependency direction and DDD-style domain modeling, plus vertical-slice/CQRS-style handlers for use-case organization.
Architectural Style
- Clean Architecture for dependency direction and framework isolation
- vertical-slice/CQRS-style organization for commands, queries, handlers, and endpoints
- not a classic “service layer per entity” template; the generated app is intended to group behavior around use cases
Generated Dependency Direction
Domaindepends on nothing else in the generated solution.Applicationdepends onDomain.Infrastructuredepends onApplicationandDomain.Apidepends onApplication,Infrastructure, andDomain.- In single-project mode, folders stay separated by responsibility even though they compile into one project.
- HTTP, persistence, messaging, and encryption concerns stay out of
Domain.
What Stays Where
Domain: business entities, invariants, repository contracts, specifications, value objects, domain events, and no infrastructure frameworks.Application: commands, queries, handlers, and use-case orchestration over domain contracts.Infrastructure: EF Core, Identity/OpenIddict, messaging transports, email senders, encryption, caching implementations, and external integrations.Apior top-level host: endpoint mapping, middleware, auth policies, OpenAPI/Scalar, service registration, and environment-specific startup behavior.
This is the main rule the template is trying to preserve: dependencies point inward toward the domain model, while frameworks and operational concerns stay at the edges.
Layer Responsibilities
Domain: entities, value objects, domain events, repository contracts, core rules. No infrastructure dependencies.Application: commands/queries, handlers, and orchestration of use-cases using domain contracts.Infrastructure: EF Core, Identity/OpenIddict wiring, email providers, repository implementations, external integrations.Api(multi-project) orEndpoints+Program.cs(single-project): HTTP transport, endpoint mapping, auth policies, middleware.
Dependency Direction
Domaindepends on nothing else.Applicationdepends onDomain.Infrastructuredepends onApplicationandDomain.Apidepends on all required layers and composes the app at startup.
Typical Request Flow
- Endpoint receives HTTP request and maps payload to command/query.
- Application handler executes use-case through domain contracts/repositories.
- Domain entities enforce invariants and may raise domain events.
- Infrastructure persists state and publishes/handles events.
- Result is mapped to consistent HTTP responses/ProblemDetails.
Auth and Security Notes
--authautomatically enables--security.- Password reset endpoints do not return reset tokens in API responses.
- OAuth demo endpoints (
/oauth/demo/*) and OpenIddict dev endpoints (/dev/openiddict/*) are mapped only in Development. - Default demo/scalar client id is
OpenIddict:Clients:Web:ClientId(defaults tomca-web-client). You can override per-request with/oauth/demo/start?clientId=.... - Development defaults seed a bootstrap admin (
admin@example.com/Admin123!) viaappsettings.Development.json. - OpenIddict dev client redirect URIs are seeded from both
App:BaseUrland runtimeASPNETCORE_URLS, reducing localhost port mismatch issues. - Bootstrap admin seeding is controlled by
Seed:*settings (appsettings.jsondefaults to disabled;appsettings.Development.jsonenables a demo admin by default). - Outside Development, OpenIddict client secret and certificate settings are validated on startup.
External Sign-In (Google, Microsoft, GitHub)
Use this when your generated app includes --auth.
- Enable provider handlers:
// Single-project:
// Infrastructure/Configuration/IdentityServiceExtensions.cs
// Multi-project:
// MCA.Api/Configuration/IdentityServiceExtensions.cs
// Uncomment providers:
// .AddGoogle(...)
// .AddMicrosoftAccount(...)
// .AddGitHub(...)
- Install GitHub provider package if needed:
dotnet add package AspNet.Security.OAuth.GitHub
- Add secrets via user-secrets/environment variables:
{
"Authentication": {
"Google": { "ClientId": "...", "ClientSecret": "..." },
"Microsoft": { "ClientId": "...", "ClientSecret": "..." },
"GitHub": { "ClientId": "...", "ClientSecret": "..." }
}
}
- Configure provider callback URLs:
- Google:
https://localhost:<port>/signin-google - Microsoft:
https://localhost:<port>/signin-microsoft - GitHub:
https://localhost:<port>/signin-github
- Optional: uncomment external-provider buttons in:
- Single:
Endpoints/AuthEndpoints.cs - Multi:
MCA.Api/Endpoints/AuthEndpoints.cs
Validate Templates Locally
pwsh ./templates/scripts/validate-templates.ps1 `
-TemplatePackagePath ./artifacts/packages `
-LocalFeedPath ./artifacts/packages `
-McaVersion 0.1.18 `
-Framework net10.0
Validation behavior:
- The script uses the local feed for
MinimalCleanArch.*packages andnuget.orgfor third-party packages by default. - This keeps validation deterministic on clean machines and CI agents.
- Pass
-IncludeNugetOrg:$falseonly if your local feed also contains every external package referenced by the generated templates. - Pass
-RunDockerE2Ewhen you want durable SQL Server and PostgreSQL integration tests to run instead of being skipped.
Uninstall
dotnet new uninstall MinimalCleanArch.Templates
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.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.18 | 29 | 3/13/2026 |
| 0.1.18-preview | 64 | 3/12/2026 |
| 0.1.17 | 76 | 3/12/2026 |
| 0.1.17-preview | 78 | 3/8/2026 |
| 0.1.16-preview | 77 | 3/7/2026 |
| 0.1.15-preview | 84 | 3/3/2026 |
| 0.1.14 | 86 | 3/2/2026 |
| 0.1.14-preview | 84 | 3/1/2026 |
| 0.1.13-preview | 87 | 2/28/2026 |
| 0.1.12-preview | 90 | 2/22/2026 |
| 0.1.11-preview | 105 | 12/27/2025 |
| 0.1.10-preview | 91 | 12/27/2025 |
| 0.1.9-preview | 122 | 12/21/2025 |
| 0.1.8-preview | 225 | 12/15/2025 |
| 0.1.7 | 163 | 12/14/2025 |
| 0.1.7-preview | 416 | 12/11/2025 |
| 0.1.6 | 441 | 12/9/2025 |
| 0.1.6-preview | 433 | 12/9/2025 |