ModularMonolith.Solution.Template 2.1.0

dotnet new install ModularMonolith.Solution.Template@2.1.0
                    
This package contains a .NET Template Package you can call from the shell/command line.

StarterKit — Modular Monolith Core for ASP.NET Core

The core of the StarterKit Modular Monolith template: the reusable C#/.NET framework building blocks (built on the private "Light" framework family — Lightsoft.* packages), a composition-root host with a .NET Aspire app host for local development, and two business modules — Identity (the reference module) and Notifications — with their tests. Client apps are not part of the .NET solution; the repository carries one, the clients/admin admin console. Meant to be cloned, forked, or installed as a dotnet new template as the starting point for new projects.

Getting Started

Backend

dotnet build StarterKit.slnx
dotnet run --project src/StarterKit.AppHost                              # API + Redis + RabbitMQ + Aspire dashboard
dotnet run --project src/StarterKit.WebApi/StarterKit.WebApi.csproj      # or the API on its own (in-memory cache, no-op bus)
dotnet test --solution StarterKit.slnx

Database provider and schema setup, configuration, test filters, and migrations: docs/conventions/development-guide.md.

Client (clients/admin)

cd clients/admin
pnpm install
cp .env.example .env.local   # then fill in the vars listed in .env.example
pnpm dev

The required environment variables are described in clients/admin/docs/conventions/development-guide.md. All env vars are server-only (never NEXT_PUBLIC_). The backend must be running and reachable at the configured API base URLs for auth and data pages to work, and its CORS policy must allow the admin app's origin for the SignalR notification hub to connect directly from the browser. Under the Aspire app host (StarterKit.AppHost), the admin client is started alongside the API.

Install as a template

The repository packs into one NuGet template package, ModularMonolith.Solution.Template. Pack it from the repo root, install it, and generate from it:

nuget pack ModularMonolith.nuspec -NoDefaultExcludes      # -NoDefaultExcludes keeps the dot-folders (.template.config) in the package
dotnet new install ./ModularMonolith.Solution.Template.<version>.nupkg

dotnet new mm-sln -n MyApp          # a whole solution; "StarterKit" is renamed to MyApp
dotnet new mm -n Billing            # a single-project module (Billing + Billing.Contracts)
dotnet new ca-mm -n Billing         # a Clean Architecture module (Domain, Application, Infrastructure, Contracts)

Run dotnet new mm / ca-mm inside the new solution's src/ folder so the generated project references (..\Shared, ..\Infrastructure, …) resolve, then add the projects to the solution and register the module in StarterKit.WebApi. Uninstall with dotnet new uninstall ModularMonolith.Solution.Template. Pack from a clean working tree: the package contains whatever files are on disk, including local appsettings.json edits.

Status — what's built

Piece Status
src/Shared, src/Infrastructure, src/Persistence, src/EventBusMassTransitRabbitMQ (framework building blocks) ✅ built
src/Identity + src/Identity.Contracts — users, roles, claims, self-issued JWT/refresh/session/hub tokens, Active Directory, permission catalog ✅ built, tested
src/Identity.Web — Razor Pages login, Microsoft Entra ID (OIDC) external login with a PKCE authorization-code relay for separate-origin clients, and admin pages for users, roles, and permissions — co-hosted in StarterKit.WebApi or standalone ✅ built
src/Notifications + src/Notifications.Contracts — notification storage, SignalR push, SMTP mail, welcome-mail consumer of Identity's integration event ✅ built, tested
src/Migrations/{MSSQL,PostgreSQL,Sqlite} — per-provider EF Core migrations and migrate-and-seed console apps ✅ built — see docs/conventions/migrations.md
src/StarterKit.WebApi (composition-root host), src/StarterKit.AppHost + src/StarterKit.ServiceDefaults (.NET Aspire local orchestration) ✅ built — runnable API
tests/Framework.Tests, tests/Identity.Tests, tests/Notifications.Tests (xUnit v3) ✅ built
clients/admin (Next.js admin console) — real auth (password or Microsoft), permission-gated admin screens over Identity and Notifications, real-time notifications — see clients/admin/CLAUDE.md ✅ built
dotnet new templates — solution (mm-sln) and module projects (mm, ca-mm) packed by ModularMonolith.nuspec ✅ built — see Install as a template
Further business modules and additional clients/* apps ❌ not part of this branch

Structure

Projects, grouped by solution folder in StarterKit.slnx:

StarterKit.slnx
├── /src/_framework/
│   ├── src/Shared                          (shared kernel)
│   ├── src/Infrastructure                  (ASP.NET Core hosting building blocks)
│   ├── src/Persistence                     (EF Core building blocks)
│   └── src/EventBusMassTransitRabbitMQ     (integration-event bus)
├── /src/
│   ├── src/StarterKit.WebApi               (composition root, the only deployable)
│   ├── src/StarterKit.AppHost              (.NET Aspire app host — local orchestration, Redis/RabbitMQ containers, dashboard)
│   └── src/StarterKit.ServiceDefaults      (.NET Aspire service defaults — telemetry, service discovery, resilience)
├── /src/identity-module/
│   ├── src/Identity.Contracts              (the module's cross-module seam)
│   ├── src/Identity                        (module implementation — JSON API, token issuance, persistence)
│   └── src/Identity.Web                    (Razor Pages login, Microsoft login relay, and admin pages — co-hosted or standalone)
├── /src/notifications-module/
│   ├── src/Notifications.Contracts         (the module's cross-module seam)
│   └── src/Notifications                   (module implementation — notification storage, SignalR push, SMTP mail)
├── /src/_migrations/
│   ├── src/Migrations/MSSQL                (EF migrations + migrate-and-seed console app, SQL Server)
│   ├── src/Migrations/PostgreSQL           (same, PostgreSQL)
│   └── src/Migrations/Sqlite               (same, Sqlite)
└── /tests/
    ├── tests/Framework.Tests               (framework projects)
    ├── tests/Identity.Tests                (Identity module)
    └── tests/Notifications.Tests           (Notifications module)

Outside the solution:

clients/
└── admin/                                  (Next.js admin console — consumes the Identity and Notifications APIs over HTTP)

.template.config/                           (`dotnet new` solution template `mm-sln` — the whole repository)
templates/
├── module/                                 (`dotnet new mm` — single-project module + Contracts)
└── ca-module/                              (`dotnet new ca-mm` — Clean Architecture module: Domain, Application, Infrastructure, Contracts)
ModularMonolith.nuspec                      (packs the above as one NuGet template package)

Project responsibilities and the dependency rules are in CLAUDE.md; the exact project references are in docs/architecture/dependency-graph.md. The admin client is documented in clients/admin/CLAUDE.md, and the backend ↔ client boundary in docs/integration.md.

Architecture Diagram

graph TD
    Client["Separate-origin client"]
    AppHost["StarterKit.AppHost<br/>Aspire (local dev)"]
    WebApi["StarterKit.WebApi<br/>composition root"]
    SD["StarterKit.ServiceDefaults"]
    Migrators["src/Migrations/*<br/>migrate + seed"]

    subgraph IdentityModule["Identity module"]
        IdW["Identity.Web<br/>Razor Pages"]
        Id["Identity<br/>implementation"]
        IdC["Identity.Contracts<br/>seam"]
    end

    subgraph NotificationsModule["Notifications module"]
        Nt["Notifications<br/>implementation"]
        NtC["Notifications.Contracts<br/>seam"]
    end

    subgraph Framework["Framework"]
        Infra["Infrastructure"]
        Persistence["Persistence"]
        Bus["EventBusMassTransitRabbitMQ"]
        Shared["Shared<br/>(leaf)"]
    end

    Client -. HTTP/JSON, SignalR .-> WebApi
    AppHost -. runs .-> WebApi
    WebApi --> SD
    WebApi --> IdentityModule
    WebApi --> NotificationsModule
    WebApi --> Framework
    Migrators --> IdentityModule
    Migrators -- MSSQL only --> NotificationsModule
    Migrators --> Framework
    IdW --> Id
    Id --> IdC
    IdentityModule --> Infra & Persistence
    Nt --> NtC
    Nt --> IdC
    Nt --> Infra & Persistence & Bus
    IdC --> Shared
    NtC --> Shared
    Infra & Persistence & Bus --> Shared

    classDef leaf fill:#2f6f4f,stroke:#1e4a34,color:#fff;
    class Shared leaf;

Login Flow (client ↔ server)

A separate-origin client has two sign-in paths that both end with the client holding the same token pair (access + refresh token). See Identity for the module's mechanics — this is the shape, not the detail.

sequenceDiagram
    actor U as Browser
    participant C as Client
    participant W as Identity.Web (in WebApi)
    participant I as Identity module (in WebApi)
    participant M as Microsoft Entra ID

    rect rgb(235, 245, 255)
    note over U,I: Password login
    U->>C: submit credentials
    C->>I: POST api/v1/auth/token/get
    I-->>C: TokenDto
    C-->>U: client stores the token pair
    end

    rect rgb(240, 255, 240)
    note over U,M: Microsoft login (PKCE authorization-code relay)
    U->>C: start Microsoft sign-in
    C-->>U: 302 → Identity.Web (state, PKCE code_challenge, client keeps the verifier)
    U->>W: GET /Account/ExternalLoginStart
    W-->>U: 302 → Microsoft sign-in
    U->>M: authenticate
    M-->>U: 302 → Identity.Web (/signin-oidc)
    U->>W: OIDC callback (/Account/ExternalLoginRelay)
    W->>I: resolve user, mint token (in-process, same module)
    W-->>U: 302 → client redirectUri?code=...&state=...
    U->>C: GET redirectUri?code=...
    C->>I: POST api/v1/auth/token/external {code, codeVerifier}
    I-->>C: TokenDto (code now consumed, single-use)
    C-->>U: client stores the token pair
    end

Access tokens are renewed through POST api/v1/auth/token/refresh. The client's redirectUri must be allow-listed in ExternalLoginRelay:AllowedRedirectUris.

Tech Stack

Layer Stack
Runtime ASP.NET Core (C#), net10.0
Architecture Modular Monolith — see Structure
Data access EF Core — provider-configurable via DbProvider (InMemory / PostgreSQL / MSSQL / Sqlite)
Authentication ASP.NET Core Identity; self-issued JWT (Bearer) for the API; cookie for the Razor Pages; optional Microsoft Entra ID (OIDC) external login
Messaging MassTransit over RabbitMQ for integration events; a no-op bus when disabled
Real-time / mail SignalR hub for real-time notification push; SMTP mail (Lightsoft.SmtpMail)
Observability / local orchestration Serilog; OpenTelemetry via .NET Aspire service defaults; Aspire app host and dashboard for local development, also running Redis and RabbitMQ containers
Vendor framework Lightsoft.* package family (mediator, Result/Paged contracts, domain base types, ASP.NET Core authorization/modularity helpers, caching, Serilog, event bus, Active Directory, SMTP mail)
Validation / mapping FluentValidation, Mapster
Testing xUnit v3 + Moq (via tests/ModuleTests.props) on Microsoft.Testing.Platform (selected by the root global.json)
Client clients/admin/ — Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS v4, pnpm. Encrypted-cookie sessions (password or Microsoft login, proactive token refresh); real-time notifications over SignalR. Currently the only client app

Package versions are managed centrally in Directory.Packages.props.

Documentation

License

MIT — see LICENSE.


Last synced: 2026-10-13

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
2.1.0 56 10/13/2026
Loading failed

* Solution template mm-sln: framework, host, Identity and Notifications modules, Next.js admin client
     * Module templates: mm (single project + Contracts) and ca-mm (Domain/Application/Infrastructure + Contracts)
     * Module templates now follow the real module layout: StarterKit.Modules.ModuleName namespaces, AppModule/AppModuleConsumer scaffolding, AddModuleNameServices registration
     * Fixed the corrupted ca-mm Domain project file