Porfolio & Blog CMS is structured around Clean Architecture — a layering strategy that keeps business logic completely independent of frameworks, databases, and delivery mechanisms. The Domain and Application layers contain every rule and use case that matters to the product; they have zero knowledge of ASP.NET Core, Entity Framework, or Blazor. Infrastructure, Api, and UI are outer rings that implement interfaces defined in the inner layers, which means the entire technology stack can be swapped without touching a single business rule.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Andrespeerez/porfolio-blog/llms.txt
Use this file to discover all available pages before exploring further.
The Dependency Rule
Clean Architecture has one inviolable constraint: source-code dependencies can only point inward. Outer layers may depend on inner layers; inner layers must never import anything from an outer layer. Domain knows nothing about Application, Application knows nothing about Infrastructure, and neither knows anything about the web framework or the UI renderer.If you find yourself importing an
Infrastructure or Api namespace inside Domain or Application, that is a Clean Architecture violation. Use an interface (port) in the inner layer and inject the concrete implementation from outside.Layer overview
Domain
The Domain layer is the innermost ring and carries no framework dependencies whatsoever — not even a NuGet reference to ASP.NET Core. Its sole aggregate is theUser entity, which protects its own invariants through a static factory method:
Domain/Entities/User.cs
PasswordHash has a private set, ensuring the hash can only be assigned at construction time through the factory. The IPasswordHasher dependency is defined in Application and passed in, so Domain itself remains free of any concrete hashing library.
Application
The Application layer orchestrates business workflows. It defines:- Use cases —
AuthenticateUser,RegisterUser, andLogoutUser. Each exposes a singleExecuteAsyncmethod and returns a typed result record. - Port interfaces —
IUserRepository,IPasswordHasher, andISessionManager. These are the contracts that Infrastructure must satisfy; Application never imports the concrete classes. - DTOs —
LoginRequest(email, password, rememberMe flag),AuthResult(success flag + optional error message), andRegisterResult(success flag, new user Id, optional error message).
Application/DTOs/AuthResult.cs
Application/DTOs/RegisterResult.cs
Infrastructure
Infrastructure is the outermost implementation layer. It provides concrete adapters for every port defined in Application:UserRepository— implementsIUserRepositoryusing Entity Framework Core with a SQLite database. Queries theAppDbContext.UsersDbSet<User>and callsSaveChangesAsync()on writes.IdentityPasswordHasher— implementsIPasswordHasherby wrappingIPasswordHasher<User>fromMicrosoft.Extensions.Identity.Core. This keeps the Application layer free from any Identity package references.CookieSessionManager— implementsISessionManagerusingIHttpContextAccessor. It builds aClaimsPrincipalfrom the authenticated user’s Id and email, then calls ASP.NET Core’sHttpContext.SignInAsync/SignOutAsync.
Api
The Api layer contains ASP.NET Core Minimal API extension methods that map HTTP routes to use-case invocations. The two endpoints are:MapLogin— handlesPOST /api/auth/login, deserializes aLoginRequest, delegates toAuthenticateUser.ExecuteAsync, and returns200 OKor a400 Bad Requestwith the error message.MapLogout— handlesPOST /api/auth/logout, delegates toLogoutUser.ExecuteAsync, and redirects to/login.
Program.cs with app.MapLogin() and app.MapLogout(), keeping route setup in one place.
UI
The UI layer is a Blazor Server application. Components and pages are purely presentational — they inject use cases directly via the ASP.NET Core DI container and never touch repositories or database contexts. The<AuthorizeView> component and [Authorize] attribute gate access to admin pages. Because the UI layer sits outside the Application layer in the dependency graph, it can be replaced by a different frontend (e.g., Blazor WebAssembly, a separate React SPA) without any business logic changes.
Service registration
Program.cs wires every port to its adapter and registers each use case as a scoped service, following the standard ASP.NET Core DI pattern:
Program.cs
Request flow
The following describes how a login request travels through every layer, from the browser to the cookie being set:- HTTP POST
/api/auth/loginarrives at the ASP.NET Core pipeline. - Api layer —
MapLogindeserializes the request body into aLoginRequestDTO and callsAuthenticateUser.ExecuteAsync(email, password). - Application layer —
AuthenticateUsercallsIUserRepository.GetByEmailAsync(email)to fetch the user record. - Infrastructure (UserRepository) — EF Core executes a
SELECTagainst the SQLiteUserstable and returns aUser?. - Application layer —
AuthenticateUserpasses the stored hash and the submitted password toIPasswordHasher.Verify(hashedPassword, password). - Infrastructure (IdentityPasswordHasher) — delegates to ASP.NET Core Identity’s
IPasswordHasher<User>.VerifyHashedPasswordand returnstrueorfalse. - Application layer — on success, calls
ISessionManager.SignInAsync(user). - Infrastructure (CookieSessionManager) — builds a
ClaimsPrincipalwithNameIdentifierandEmailclaims and callsHttpContext.SignInAsync, issuing the authentication cookie. - Api layer —
MapLoginreceivesAuthResult.Ok()and returns200 OKto the browser. - The browser stores the cookie; all subsequent requests are authenticated automatically.