fullstackhero is an opinionated, production-first .NET 10 starter for building multi-tenant SaaS and enterprise APIs. You get the full source — BuildingBlocks, Modules, and a composition-root Host — wired through Minimal APIs, Mediator, and EF Core. No black-box NuGet packages: you own and can modify everything.
It’s aimed at teams that want to ship features on day one without spending a sprint wiring identity, tenancy, auditing, caching, jobs, storage, observability, and API docs.
Highlights
- Modular monolith, vertical slices. Each module is a bounded context with its own DbContext, contracts, and feature folders. Communication across modules goes through
*.Contractsprojects only — runtime projects never reference each other. - Multi-tenant from day one. Finbuckle-powered tenancy across Identity and module DbContexts. Tenant resolution via claim, header, or query string. Per-tenant migrations and seeding on startup.
- Identity + permission-based auth. ASP.NET Identity with JWT issue/refresh, roles, granular permissions enforced via
.RequirePermission()on endpoints. - Eventing built in. Domain events on aggregates + integration events through Mediator. Outbox-friendly entity model.
- Webhooks with HMAC signing. Tenant-scoped subscriptions, retries, and delivery logs.
- Realtime + SSE. SignalR for hubs, Server-Sent Events for one-way streaming.
- Idempotency.
Idempotency-Keyheader with cache-backed replay. - Feature flags with tenant overrides. Microsoft.FeatureManagement, scoped per tenant.
- Quotas. Per-tenant request and resource limits.
- Observability baked in. OpenTelemetry traces, metrics, and logs (OTLP); Serilog structured logging; health checks; security/exception auditing.
- API docs. OpenAPI + Scalar UI. Versioned routes via
Asp.Versioning(/api/v{version}/{module}). - Cloud-ready.
.NET AspireAppHost brings up Postgres, Valkey (a Redis-compatible, BSD-licensed Redis fork), and the API host locally with one command. Production deploy via Docker Compose included. - Two frontends. React + Vite admin console and dashboard, both in
clients/. - CLI + template. Scaffold new projects with
fsh newordotnet new fsh, or clone the repo directly.
High-level architecture
dotnet-starter-kit/├── src/│ ├── BuildingBlocks/ Shared framework libraries│ │ ├── Core DDD primitives, exceptions, abstractions│ │ ├── Persistence EF Core base contexts, specifications, soft delete│ │ ├── Web Host wiring: auth, OpenAPI, rate limit, CORS, errors│ │ ├── Caching HybridCache + Valkey│ │ ├── Eventing Domain + integration events│ │ ├── Eventing.Abstractions Contracts for cross-module events│ │ ├── Jobs Hangfire│ │ ├── Mailing MailKit / SendGrid│ │ ├── Storage Local + S3-compatible│ │ ├── Quota Per-tenant limits│ │ └── Shared Permission constants, common contracts│ ││ ├── Modules/ Bounded contexts (each = runtime + contracts pair)│ │ ├── Identity ASP.NET Identity, JWT, roles, permissions│ │ ├── Multitenancy Tenant CRUD, migrations, upgrades│ │ ├── Auditing Activity / security / exception audit trail│ │ ├── Webhooks HMAC-signed delivery, retries, logs│ │ ├── Files Upload URLs, storage abstraction│ │ ├── Notifications In-app notifications│ │ └── Billing · Catalog · Chat · Tickets Sample modules│ ││ ├── Host/│ │ ├── FSH.Starter.Api Composition root (Program.cs)│ │ ├── FSH.Starter.AppHost .NET Aspire orchestrator│ │ ├── FSH.Starter.DbMigrator Migrations + seed-demo CLI│ │ └── FSH.Starter.Migrations.PostgreSQL│ ││ ├── Tools/CLI The `fsh` CLI (Spectre.Console)│ └── Tests/ Architecture tests + per-module test projects│├── clients/│ ├── admin React + Vite admin console│ └── dashboard React + Vite dashboard│└── deploy/ Docker Compose, Dokploy, TerraformModule boundaries are enforced by NetArchTest rules in src/Tests/Architecture.Tests.
Feature slice layout
Each feature is a vertical slice. For Modules.Identity registering a user:
Modules.Identity.Contracts/v1/Users/RegisterUser/ RegisterUserCommand.cs RegisterUserResponse.cs
Modules.Identity/Features/v1/Users/RegisterUser/ RegisterUserEndpoint.cs ← Minimal API RegisterUserCommandHandler.cs ← Mediator handler RegisterUserCommandValidator.cs ← FluentValidationHandlers are public sealed, return ValueTask<T>, and use .ConfigureAwait(false). Endpoints are static extensions on IEndpointRouteBuilder.
Composition root
src/Host/FSH.Starter.Api/Program.cs wires the platform in three calls:
builder.Services.AddMediator(o => { o.Assemblies = [/* command + handler markers */]; });
builder.AddHeroPlatform(o =>{ o.EnableCaching = true; o.EnableMailing = true; o.EnableJobs = true; o.EnableQuotas = true; o.EnableSse = true; o.EnableRealtime = true;});
builder.AddModules(moduleAssemblies);
var app = builder.Build();app.UseHeroMultiTenantDatabases();app.UseHeroPlatform(p => { p.MapModules = true; /* ... */ });The API never mutates data on startup. Demo data (acme/globex tenants, sample catalog/tickets/chat) is provisioned by FSH.Starter.DbMigrator seed-demo.
Stack
Runtime
| Concern | Technology |
|---|---|
| Framework | .NET 10 / C# latest |
| Solution | .slnx (XML) with central package management (Directory.Packages.props) |
| Web | Minimal APIs, Asp.Versioning.Http 10 |
| Mediator | Mediator 3.0.2 (source generator — no reflection) |
| Validation | FluentValidation 12 |
| ORM | EF Core 10 |
| Database | PostgreSQL (Npgsql) by default; SQL Server provider available |
| Identity | ASP.NET Identity + JWT bearer (Microsoft.AspNetCore.Authentication.JwtBearer 10) |
| Multitenancy | Finbuckle.MultiTenant 10 (claim / header / query strategies) |
| Caching | HybridCache (in-memory + Valkey) via StackExchange.Redis |
| Jobs | Hangfire 1.8 (Postgres or in-memory) |
| HTTP resilience | Microsoft.Extensions.Http.Resilience (Polly v8) |
| Feature flags | Microsoft.FeatureManagement + tenant overrides |
| Realtime | SignalR (Valkey backplane) + Server-Sent Events |
| MailKit / SendGrid | |
| Storage | Local filesystem or S3-compatible (AWS SDK) |
| Messaging | RabbitMQ client (optional) |
| Logging | Serilog 4 (structured) |
| Tracing / metrics | OpenTelemetry 1.15 (OTLP exporter) |
| API docs | OpenAPI 10 + Scalar UI |
| Errors | ProblemDetails (RFC 9457) via global exception handler |
| Orchestration | .NET Aspire 13.3 (Postgres + Valkey + API) |
Frontends
| App | Stack |
|---|---|
clients/admin | React + Vite |
clients/dashboard | React + Vite |
Testing
| Layer | Tools |
|---|---|
| Unit | xUnit, Shouldly, NSubstitute, AutoFixture |
| Integration | Microsoft.AspNetCore.Mvc.Testing, Testcontainers (Postgres / Valkey / Minio) |
| Architecture | NetArchTest — enforces module boundaries |
Distribution
| Channel | Command |
|---|---|
| FSH CLI | dotnet tool install -g FullStackHero.CLI && fsh new MyApp |
dotnet new template | dotnet new install FullStackHero.NET.StarterKit && dotnet new fsh -n MyApp |
| Clone the repo | git clone https://github.com/fullstackhero/dotnet-starter-kit.git |
| GitHub Codespaces | ”Use this template” → open in Codespaces |
Where to go next
- Prerequisites — what you need installed.
- Quick Start — run a project in 60 seconds.
- Architecture — modular monolith, VSA, module boundaries.
- Modules — Identity, Multitenancy, Auditing, Webhooks.
- Guides — task-oriented walkthroughs.