Skip to main content

Introduction

FullStackHero .NET Starter Kit is a modular monolith designed for building production-ready, multi-tenant applications. It combines the deployment simplicity of monoliths with the organizational benefits of microservices through well-defined module boundaries.

Architecture Diagram

┌─────────────────────────────────────────────────────────────┐
│                     Playground.Api (Host)                    │
│  ┌───────────────────────────────────────────────────────┐  │
│  │  AddModules() → ConfigureServices() → MapEndpoints()  │  │
│  └───────────────────────────────────────────────────────┘  │
└───────────────────┬─────────────────────────────────────────┘

        ┌───────────┴──────────┬──────────────┐
        ▼                      ▼              ▼
┌──────────────┐      ┌──────────────┐  ┌──────────────┐
│   Identity   │      │ Multitenancy │  │   Auditing   │
│    Module    │      │    Module    │  │    Module    │
│              │      │              │  │              │
│ IModule impl │      │ IModule impl │  │ IModule impl │
└──────┬───────┘      └──────┬───────┘  └──────┬───────┘
       │                     │                 │
       └─────────────────────┴─────────────────┘
                             |
                ┌────────────┴───────────┐
                ▼                        ▼
        ┌──────────────┐        ┌──────────────┐
        │ BuildingBlock│        │    Shared    │
        │   Framework  │        │  Contracts   │
        │              │        │              │
        │ • Core       │        │ • Identity   │
        │ • Persistence│        │ • Multitenancy│
        │ • Web        │        │ • Constants  │
        │ • Caching    │        │              │
        │ • Jobs       │        │              │
        │ • Mailing    │        │              │
        └──────────────┘        └──────────────┘

Core Architectural Principles

1. Modular Monolith

The application is structured as independent modules that communicate through well-defined contracts:
  • Identity Module: Authentication, authorization, users, roles, groups, sessions
  • Multitenancy Module: Tenant management, provisioning, theme customization
  • Auditing Module: Audit trail for HTTP requests and domain events
Each module implements the IModule interface:
namespace FSH.Framework.Web.Modules;

public interface IModule
{
    // DI/Options/Health/etc. — don't depend on ASP.NET types here
    void ConfigureServices(IHostApplicationBuilder builder);

    // HTTP wiring — Minimal APIs only
    void MapEndpoints(IEndpointRouteBuilder endpoints);
}

2. Vertical Slice Architecture

Features are organized as self-contained vertical slices, not horizontal layers:
Modules.Identity/Features/v1/Groups/CreateGroup/
├── CreateGroupCommandHandler.cs    ← Business logic
├── CreateGroupCommandValidator.cs  ← Validation rules
└── CreateGroupEndpoint.cs          ← HTTP endpoint

Modules.Identity.Contracts/v1/Groups/CreateGroup/
└── CreateGroupCommand.cs           ← Contract (ICommand<T>)
Each feature contains:
  • Command/Query: Request DTO implementing ICommand<T> or IQuery<T>
  • Handler: Business logic implementing ICommandHandler or IQueryHandler
  • Validator: FluentValidation rules
  • Endpoint: Minimal API endpoint mapping

3. CQRS with Mediator

Command Query Responsibility Segregation using the Mediator library (not MediatR):
public sealed record CreateGroupCommand(
    string Name,
    string? Description,
    bool IsDefault,
    List<string>? RoleIds) : ICommand<GroupDto>;
Handlers return ValueTask<T> (not Task<T>) for better performance.

4. Domain-Driven Design

Rich domain models with encapsulated behavior:
  • Entities: BaseEntity<TId> with domain events
  • Aggregates: AggregateRoot<TId> for consistency boundaries
  • Value Objects: Immutable types for domain concepts
  • Domain Events: DomainEvent for cross-aggregate communication
Building blocks are located in BuildingBlocks/Core/Domain/.

5. Multi-Tenancy First

Built-in multi-tenancy using Finbuckle.MultiTenant:
  • Tenant Resolution: Header, claim, and query string strategies
  • Data Isolation: Database-per-tenant pattern
  • Distributed Cache: Cached tenant info for performance
  • Tenant Context: Automatic tenant tracking on entities

Key Design Decisions

Minimal APIs

No controllers. All endpoints use Minimal API routing for better performance and simplicity.

Mediator (not MediatR)

Uses Mediator library with ICommand/IQuery interfaces and ValueTask returns.

Database Per Tenant

Each tenant gets its own database for maximum isolation and security.

Outbox Pattern

Transactional outbox ensures reliable event publishing with Hangfire.

Technology Stack

1

.NET 10

Latest .NET features including native AOT support and improved performance.
2

Entity Framework Core

Code-first database design with PostgreSQL support.
3

Mediator

In-process messaging for CQRS commands and queries.
4

FluentValidation

Declarative validation rules for all commands and queries.
5

Finbuckle.MultiTenant

Production-ready multi-tenancy with multiple resolution strategies.
6

Hangfire

Background jobs for outbox processing and scheduled tasks.

Module Communication

Modules communicate through:
  1. Shared Contracts: Published DTOs and interfaces in .Contracts projects
  2. Integration Events: Published to outbox, consumed asynchronously
  3. Direct Service Calls: For synchronous operations within bounded contexts
Modules must never reference other module implementations, only their contracts. This enforces loose coupling.

Building Blocks

The framework provides 11 building block packages:
PackagePurpose
CoreDomain primitives, exceptions, context abstractions
PersistenceDbContext base, repositories, interceptors
WebModule loader, middleware, exception handling
CachingDistributed and hybrid cache services
JobsHangfire integration for background tasks
MailingEmail templating and SMTP configuration
StorageFile storage abstraction (local, cloud)
EventingDomain events and outbox pattern
SharedCommon constants and DTOs
Blazor.UIBlazor components and theming
OpenAPISwagger/OpenAPI documentation

Next Steps

Modular Monolith

Learn how modules are loaded and isolated

Vertical Slices

Understand the feature folder structure

CQRS & Mediator

Deep dive into commands, queries, and handlers

Domain-Driven Design

Explore entities, aggregates, and domain events

Build docs developers (and LLMs) love