Pottmayer.Tars is a modular .NET framework of reusable building blocks for backend applications: primitives and mediator, data access, messaging, identity, caching, observability and more. It ships as 53 small, focused NuGet packages instead of a single monolith, so an application references only what it uses.
- Granular by design. Each family is split into
Abstractions, a runtime and one or more providers or host integrations, so contracts never drag an implementation (or ASP.NET Core) along. - One method per registration. Every piece has its own
AddTars*extension, registered withTryAddso the host can override it, and options are validated at startup. - Documented per family. Each family has its own guide under
docs/.
Requires .NET 10.
| Family | What it gives you | Docs |
|---|---|---|
| Core | Result/Error/Optional primitives, mediator with pipeline behaviors, CQRS helpers, DDD building blocks, localization |
Core |
| Data | Provider-agnostic repositories and unit of work; relational provider (EF Core + Dapper) and MongoDB provider; multi-database coordination and multitenant connections | Data |
| Messaging | Integration events with an in-process bus, RabbitMQ and Kafka over MassTransit, several brokers in one process, transactional outbox | Messaging |
| Security | Identity (JWT, refresh token rotation, revocation, magic link, API key, OAuth, ready-made endpoints) and DataProtection (AES-GCM secret protection with key rotation) | Identity |
| Caching | Cache abstractions with in-memory and Redis providers | Caching |
| Multitenancy | Tenant resolution pipeline, tenant context, catalog and store, per-tenant execution | Multitenancy |
| Web | HTTP response envelopes, error mapping, response wrapping and pagination for MVC and Minimal APIs | Web |
| User Context | Current-user resolution from claims, typed or claims-based | User Context |
| Observability | OpenTelemetry traces, metrics and logs over OTLP, native ILogger or Serilog, correlation id |
Observability |
| Communication | E-mail (logging fake and MailKit SMTP) and the Telegram Bot API (multi-bot, long polling or webhook) | Communication |
| AI | Chat completion with tool calling and multimodal input behind one contract, provider chosen per call; Gemini provider | AI |
The full list of packages and what each one contains is in the package matrix.
The packages are published to GitHub Packages, not nuget.org. GitHub Packages requires authentication even to read, so you need a GitHub personal access token (classic) with the read:packages scope.
-
Add the feed next to nuget.org.
nuget.config.exampleis a starting point:<packageSources> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="github" value="https://nuget.pkg.github.com/leonardopottmayer/index.json" /> </packageSources>
-
Keep the token out of the repository: reference an environment variable instead of writing it in the file.
<packageSourceCredentials> <github> <add key="Username" value="YOUR_GITHUB_USERNAME" /> <add key="ClearTextPassword" value="%GITHUB_PACKAGES_TOKEN%" /> </github> </packageSourceCredentials>
-
Reference the packages you need, all at the same version:
dotnet add package Pottmayer.Tars.Communication.Telegram --version 0.0.18
Every family follows the same shape: bind the options, register the pieces you use, resolve the contract. Here, sending a Telegram message from a Minimal API:
using Pottmayer.Tars.Communication.Telegram.Abstractions;
using Pottmayer.Tars.Communication.Telegram.Abstractions.Models;
using Pottmayer.Tars.Communication.Telegram.DI;
var builder = WebApplication.CreateBuilder(args);
builder.AddTarsTelegramOptions(); // binds and validates Tars:Communication:Telegram
builder.Services.AddTarsTelegramHttpClient(); // the shared HttpClient every bot uses
builder.Services.AddTarsTelegramClientFactory(); // resolves a bot by name
var app = builder.Build();
app.MapPost("/notify", async (string chatId, string text, ITelegramClientFactory telegram) =>
{
await telegram.GetClient().SendMessageAsync(new TelegramMessage(chatId, text));
return Results.Ok();
});
app.Run();{
"Tars": {
"Communication": {
"Telegram": {
"Bots": { "default": { "BotToken": "set it through an environment variable or user secrets" } }
}
}
}
}Each family's guide has the same walk-through for its own packages, from the minimal setup to the complete one.
- Lockstep versioning. Every package is published at the same version, so a set of
Pottmayer.Tars.*references always moves together. - Pre-1.0. The
0.0.xline can change public APIs between versions. Each release lists what changed and what to adapt under Compatibility. - Release notes: GitHub Releases.
- Documentation index: every family, read by capability ("configure identity") or by reference ("which package has this contract").
- Package taxonomy: the four package levels (Abstractions, Runtime, Provider, Host Integration) and the naming rules.
- Coding conventions:
OptionsvsConfiguration, one method per registration,TryAdd,AddTars*naming, fail-fast validation. - Data, Multitenancy and Multi-Database: the in-depth data guide.
- Publishing: packing and publishing the packages.
dotnet build Pottmayer.Tars.slnxdotnet test Pottmayer.Tars.slnxUnit tests live under tests/, one project per family (xUnit v3 on Microsoft.Testing.Platform, AwesomeAssertions and Moq).
Pottmayer.Tars is proprietary, not open source. The source is public for reference and evaluation only: using, copying, modifying or distributing it, in source or binary form, requires prior written permission from the copyright holder. See LICENSE.
