Skip to content

Architecture

Pragmatic Design organizes its modules in three layers, each building on the one below:

Layer 0 (Foundation) Layer 1 (Capabilities) Layer 2 (Integration)
├── Result ├── Validation ├── Actions
├── Ensure ├── Mapping ├── Endpoints
├── DependencyInjection ├── Internationalization ├── Persistence
└── Abstractions ├── Resilience └── Composition
├── Configuration
├── Caching
└── Specification

Foundation modules have zero dependencies on each other. Capabilities depend only on Foundation. Integration modules can depend on any lower layer.

This is the key architectural insight: adding a NuGet reference is the configuration.

When you add Pragmatic.Persistence.EFCore to your project, the Source Generator detects it via FeatureDetector and starts generating repositories, entity configurations, and query filters. Remove the package — the generated code disappears.

No flags, no if statements, no configuration files. Just your .csproj.

Attributes like [Module], [BelongsTo], and [Include] define your architecture. The Source Generator reads these and understands your module boundaries.

[Module]
[Include<CatalogModule, AppDatabase>]
public class CatalogBoundary;

IPragmaticBuilder extension methods configure infrastructure choices:

await PragmaticApp.RunAsync(args, app =>
{
app.UseMultiTenancy(mt => mt.UseHeader());
app.UseAuthentication<JwtAuthHandler>("Bearer");
app.UseLogging(log => log.AddConsole());
});

Business-specific service registration:

[StartupStep]
public class AppStartupStep : IStartupStep
{
public int Order => 60;
public void ConfigureServices(IServiceCollection services,
IConfiguration config, IHostEnvironment env)
{
services.AddPragmaticServices();
services.AddGeneratedValidators();
}
}