.NET Minimal API starter kits with MongoDB, dual pagination, and ErrorOr baked in — Redis, Keycloak, and S3 for the kits that need them. Configure and run.
One-time payment · Unlimited projects · Lifetime access
Six kits
Start minimal, add layers as you need them. Almost every kit includes .NET 8 and .NET 10 (at the same price).
_id index, consistent under concurrent writes/health/live and /health/ready with MongoDB probe, Docker health-check gated startup
Authenticated (any valid JWT) and AdminOnly (admin realm role)
NullCacheService to disable with one flag/health/ready; Valkey 7.2 included
GetCacheKey, GetPagedCacheKey, GetCursorCacheKey, GetInvalidationTagsNullCacheService to disable with one flagAuthenticated, AdminOnly), OAuth2 PKCE in Swagger, pre-built realm export
GetCacheTtl, GetNotFoundError, OnAfter* (post-success), OnFailed* (rollback)GetCacheTtl — bound cache TTL per entity type; set shorter than presigned URL expiry to avoid stale linksGetNotFoundError — return domain-specific not-found errors instead of the generic fallbackOnAfterCreate/Update/Delete — post-success side effects: events, notifications, external cache invalidationOnCreateFailed/UpdateFailed/DeleteFailed — rollback hooks: reverse any side effect if the DB write fails
appsettings.json, zero code changes/jobs, MongoDB-backed persistence, configurable retry with exponential back-offPagination
Classic numbered navigation. Returns totalCount, totalPages, hasNext, hasPrev.
O(log n) via MongoDB _id index. Consistent under concurrent writes. No degradation as the collection grows.
64f1a2b3c4d5e6f9The hook system
BaseRepository runs every CRUD operation. Override only the hooks that matter for your domain — 19 hooks validated against the real source code.
Check uniqueness, business rules, and constraints before any write. Return Error to abort cleanly before the DB is touched.
ErrorOr<Success>Validate the fully merged entity. Receives both the original and the enriched entity — compare them to enforce business rules.
ErrorOr<Success>Guard against invalid deletions: check relations, enforce cascade rules, or block soft-deletes when conditions aren't met.
ErrorOr<Success>Enrich with server-side computed fields: slugs, tenant IDs, audit timestamps. These values must never come from the client.
ErrorOr<TEntity>Recompute derived fields after an update: re-slug, recalculate denormalized fields. Receives original + request.
ErrorOr<TEntity>Build the full single-item response. Compute derived fields, format values, load relations. Called by GetByIdAsync and CreateAsync.
ErrorOr<TDetail>Build the lightweight list response. Smaller payloads, cleaner contracts. Called by both pagination strategies (offset and cursor). Keep this lean — omit arrays and large nested objects.
ErrorOr<TSummary>Key for a single entity by ID. Default: "{type}:{id}". Scoped per repository — no conflicts across resources.
stringKey for an offset-paged list result. Default: "{type}:paged:p{page}:s{size}". Override for custom filter or tenant keys.
stringKey for a cursor-paged list result. Default includes cursor, page size, and direction. Override for tenant-scoped or filtered keys.
stringTags to wipe on any write. Default: entity-type + ID tag. Override to add category or tenant tags. Union of old+new applied on update to cover field changes.
IEnumerable<string>Bound how long responses are cached. Return null for the global default. Set shorter than presigned URL expiry to avoid serving stale S3 links.
TimeSpan?Override to return a domain-specific not-found error (e.g. ProductErrors.NotFound(id)) instead of the generic one. Called on every null by-ID result.
ErrorRuns after a successful insert + cache invalidation. Fire events, send notifications, invalidate external systems, or trigger background jobs.
TaskRuns after a successful update + cache invalidation. Propagate change notifications, sync projections, or trigger search reindexing.
TaskRuns after a confirmed delete + cache invalidation. Delete linked S3 objects, emit deletion events, or cascade side effects to other aggregates.
TaskCalled when the DB insert fails after OnMapCreateAsync already ran. Roll back side effects — e.g. delete an S3 object that was just uploaded.
TaskCalled when the DB replace fails. Roll back any side effects performed during OnMapUpdateAsync before the database was touched.
TaskCalled when the DB delete fails after OnValidateDeleteAsync passed. Roll back any compensating actions triggered during validation before the delete ran.
Task01–07 — all kits (SPARK, GUARD, RAPID, FLICK, UPLOADS, EMBER) · 08–11 — Redis kits (RAPID / FLICK / UPLOADS / EMBER) · 12–19 — UPLOADS & EMBER
In every kit
A generic typed repository that handles all CRUD. Override only what your domain needs — most of the hooks return ErrorOr<T> so any failure aborts cleanly before the database is touched. 19 hooks validated against the real source code.
No exceptions for business logic. Every operation returns ErrorOr<T> — errors propagate to the global handler and become RFC 7807 ProblemDetails. No stack traces leaked to the client.
Offset (page numbers, total count) for back-office UIs. Cursor (O(log n) via MongoDB _id index) for feeds and large collections. Consistent under concurrent writes, no degradation.
One docker compose up --build starts everything. Health-check gated startup — API waits for every dependency before accepting requests.
/health/live and /health/ready out of the box. Each dependency checked independently so failures are actionable.
Every endpoint, model, and error documented with XML comments wired into Swagger UI. Open /swagger and everything is already there.