thisisnabi/Blogger
46.4
Weak · 20 September 2026
2.9k
lines of production code
C#
primary language
4
measurements over time
What this system is
This system is a .NET 8 blogging platform built on Clean Architecture and Domain-Driven Design principles. It provides core content management capabilities, allowing users to create, draft, and publish articles with tagging, archiving, and popularity tracking. The system also facilitates community engagement through a moderated comment and reply workflow, alongside a newsletter subscription service that handles email notifications and duplicate prevention.
Features
Add domain building blocks for entity and value object equality
The new \Blogger.BuildingBlocks\ library introduces foundational domain classes, including \Entity\<TId\>\ and \ValueObject\<T\>\, which provide standardized equality comparison and hashing logic for domain models. It also adds \AggregateRoot\<TId\>\ to manage domain events, along with supporting interfaces like \IDomainEvent\ and \IAggregateRoot\, and a \DomainException\ base class. A specific \InvalidEmailAddressException\ is included to validate email addresses using \MailAddress.TryCreate\.
src/Blogger.BuildingBlocks · high confidence
Add email sending capability with HTML support
Users can now receive emails from the application, such as engagement notifications. This change introduces an EmailService that connects to an SMTP server using configurable settings (host, port, credentials) and sends messages with UTF-8 encoding and HTML body support.
src/Blogger.Infrastructure/Services/Externals · high confidence
Added GetArticle query handler to retrieve article details
The application layer now includes a new GetArticle feature that allows users to fetch a specific article by its ID. This change introduces a query object, a handler that retrieves the article from the repository (throwing a NotFoundArticleException if the article does not exist), and a response record that maps article data such as title, body, summary, read time, author, publication date, and tags.
src/Blogger.Application/Articles/GetArticle · high confidence
Added application-layer support for retrieving articles by tag
The application layer now includes a new feature to fetch articles associated with a specific tag. This change introduces the GetTaggedArticlesQuery, its corresponding handler, and the response record, enabling users to retrieve a collection of articles filtered by tag via the article repository.
src/Blogger.Application/Articles/GetTaggedArticles · high confidence
Added archive retrieval capability for blog articles
Users can now retrieve a structured archive of blog posts, organized by year and month. This change introduces the GetArchive query and its handler within the application layer, which fetches article data from the repository and maps it into a hierarchical response containing article IDs, titles, and specific dates.
src/Blogger.Application/Articles/GetArchive · high confidence
Added capability to retrieve article tags
The application layer now includes a new feature that allows users to retrieve a collection of tags associated with articles. This is implemented via a \GetTagsQuery\ and its corresponding handler, which queries the \IArticleRepository\ to fetch tags and returns them as a collection of tag names and their usage counts.
src/Blogger.Application/Articles/GetTags · high confidence
Added handler and request/response models for retrieving popular articles
The application layer now includes the implementation for fetching popular articles. This change introduces the GetPopularArticlesHandler, which queries the article repository for the most popular items based on a requested size, along with the corresponding GetPopularArticlesQuery and GetPopularArticlesQueryResponse records to support this operation.
src/Blogger.Application/Articles/GetPopularArticles · high confidence
Added subscriber duplication check capability
The application layer now includes a new subscriber service that exposes a method to check if a subscriber already exists. This allows other parts of the system to verify subscriber uniqueness before creating new records, preventing duplicate entries.
src/Blogger.Application/Subscribers · high confidence
Infrastructure layer initialization with dependency injection and link generation
The Blogger.Infrastructure project has been added to the solution, establishing the foundational infrastructure layer. This includes a DependencyInjection configuration that registers the SQL Server database context, various repositories (Article, Comment, Subscriber), and services (Email, LinkGenerator). A new LinkGenerator service implements a snowflake-based algorithm to produce short, unique identifiers for links. Additionally, global usings and assembly markers are set up to streamline the project's structure.
src/Blogger.Infrastructure · high confidence
Initial Blogger API project scaffolding
The src/Blogger.APIs project has been introduced, providing the foundational structure for the Blogger application's web interface. This includes the Program.cs entry point which configures dependency injection for Mapster, FluentValidation, and MediatR, sets up CORS policies, and enables Swagger documentation. The project implements a convention-based endpoint registration system via the IEndpoint interface and DependencyInjection.cs, allowing endpoints to be automatically discovered and mapped. It also includes global error handling, a Dockerfile for containerization, and configuration files for development environments.
src/Blogger.APIs · high confidence
Initial Entity Framework Core configuration for Article, Comment, and Subscriber aggregates
This change introduces the persistence mapping configurations for the core domain aggregates. ArticleConfiguration defines the schema for articles, including properties for title, summary, body, read time, and status, as well as owned value objects for Author, CommentIds, Tags, and a new collection for Likes. CommentConfiguration maps comments with their associated Client details, approval links, and nested Replies. SubscriberConfiguration establishes the mapping for subscribers, linking them to articles via ArticleIds. These files provide the structural blueprint for how these domain entities are stored in the database.
src/Blogger.Infrastructure/Persistence/Configurations · high confidence
Initial Entity Framework Core persistence layer for Blogger aggregates
The infrastructure now includes the core Entity Framework Core setup for the Blogger application, introducing the \BloggerDbContext\ to manage Articles, Comments, and Subscribers. A new schema configuration file (\BloggerDbContext.Schema.cs\) defines the database structure, including the 'blog' default schema and specific table names for aggregates like Subscribers, Articles, and Comments. Additionally, a design-time context factory (\BloggerDbContextFactory.cs\) has been added to support local development and database migrations using a hardcoded SQL Server connection string.
src/Blogger.Infrastructure/Persistence · high confidence
Initial application layer scaffolding and configuration
The application layer is introduced with core infrastructure including dependency injection setup for MediatR and application services, global usings for domain aggregates, and new interfaces for email and link generation. This includes the implementation of an email confirmation feature with HTML templates and settings for link expiration, alongside service classes for article validation and subscriber management.
src/Blogger.Application · high confidence
Initial database schema for the Blogger application
The persistence layer now includes the initial Entity Framework Core migration (20240606095921\_InitDbContext) and model snapshot, establishing the foundational database structure in the 'blog' schema. This migration creates tables for Articles (including embedded Author details, Tags, and Likes), Comments, Replies, and Subscribers, along with the necessary foreign key relationships and indexes to support the core blogging features.
src/Blogger.Infrastructure/Persistence/Migrations · high confidence
Initial domain project structure and assembly marker
The Blogger.Domain project has been initialized with a basic structure, including an assembly marker interface (IAssemblyMarker) and global usings that reference the Blogger.BuildingBlocks.Domain and the CommentAggregate. This establishes the foundational namespace and dependency references for the domain layer.
src/Blogger.Domain · high confidence
Initial project scaffolding with .NET 8 and Clean Architecture structure
The repository is initialized with a .NET 8 solution (\Thisisnabi.Blogger.sln\) structured around Clean Architecture and Domain-Driven Design. This includes core source projects (\Blogger.Domain\, \Blogger.Application\, \Blogger.Infrastructure\, \Blogger.APIs\, \Blogger.BuildingBlocks\) and test projects (\Blogger.UnitTests\, \Blogger.IntegrationTests\, \Blogger.FunctionalTests\). Global build properties enforce C\# 12 features, nullable reference types, and strict warning handling via \Directory.Build.props\, while \global.json\ pins the SDK to version 8.0.6. Development tooling is standardized with an \.editorconfig\ for consistent code formatting and naming, and deployment is configured for the Liara platform via \liara.json\.
(repo-wide) · high confidence
Introduce Article domain aggregate with status, tagging, and reading time
The Article aggregate root is now defined with a Draft/Published/Deleted status lifecycle, requiring tags before an article can be published. Articles automatically calculate reading time based on word count, and tags are normalized to kebab-case identifiers. The model also supports tracking likes via client IP and includes repository interfaces for querying archives, popular articles/tags, and latest articles.
src/Blogger.Domain/ArticleAggregate · high confidence
Introduce Subscriber domain aggregate and repository
Added the Subscriber aggregate root, its value object (SubscriberId), and the ISubscriberRepository interface to the domain layer. The SubscriberId now uses System.Net.Mail.MailAddress for email storage and validates input via InvalidEmailAddressException during creation, while the repository defines the contract for creating, finding, and checking existence of subscribers.
src/Blogger.Domain/SubscriberAggregate · high confidence
Introduce command handler for publishing article drafts
The application layer now includes a dedicated command and handler for publishing drafts. Users can trigger the publish action via the PublishDraftCommand, which locates the specified draft by ID, calls its Publish method to update its state, and persists the change to the repository.
src/Blogger.Application/Articles/PublishDraft · high confidence
Introduces persistence repositories for articles, comments, and subscribers
The application now includes concrete Entity Framework Core implementations for the article, comment, and subscriber aggregates. The ArticleRepository provides methods to retrieve published articles (including latest, popular, and archive views), manage drafts, and query tags. The CommentRepository handles the storage and retrieval of comments and their replies, specifically supporting approval workflows. The SubscriberRepository manages the creation and lookup of subscriber records. These changes establish the data-access layer required for the blogging platform's core content and user features.
src/Blogger.Infrastructure/Persistence/Repositories · high confidence
New GetPopularTags query handler added to application layer
The application layer now includes a new feature to retrieve popular tags. This change introduces the GetPopularTagsQuery, its corresponding handler, and the response record, allowing the system to fetch a list of popular tags based on a specified size parameter via the article repository.
src/Blogger.Application/Articles/GetPopularTags · high confidence
New article management API endpoints
The Blogger API now exposes a comprehensive set of endpoints for managing articles and drafts. Users can create and update drafts, publish drafts to live articles, and retrieve articles via several views: a single article by ID, a paginated list with optional title filtering, an archive grouped by year and month, a list of articles by specific tag, the top 5 popular articles, and the top 7 popular tags. All endpoints are tagged under 'ArticleTag' and include request validation for fields such as title length, body content, and tag limits.
src/Blogger.APIs/Endpoints/Articles · high confidence
New comment and reply management capabilities
The application layer now supports a full comment workflow: users can submit new comments and replies to articles, which are created in a pending state and require approval via a secure link sent by email. Administrators can approve individual comments or replies using these links, and both visitors and admins can retrieve lists of approved comments for an article or approved replies for a specific comment.
src/Blogger.Application/Comments · high confidence
New comment and subscription endpoints
The API now exposes dedicated endpoints for managing blog comments and newsletter subscriptions. Users can create comments and replies, retrieve comments and replies for specific articles or comments, and approve both comments and replies. Additionally, a new endpoint allows users to subscribe to the blog using their email address.
src/Blogger.APIs/Endpoints/Comments · high confidence
Behavioural changes
Add title filter to GetArticles query
The GetArticles feature now supports filtering articles by title. The GetArticlesQuery record includes a new Title parameter, which is passed to the underlying repository to retrieve matching articles.
src/Blogger.Application/Articles/GetArticles · high confidence
Application layer restructured with new domain exceptions for draft operations
The application layer for article drafts has been reorganized into dedicated feature folders (MakeDraft and UpdateDraft) and now utilizes a shared building-block exception hierarchy. Creating a draft now throws a specific DraftAlreadyExistsException if a draft with the same ID already exists, while updating a draft handles two new error scenarios: DraftNotFoundException if the draft is missing, and DraftTitleDuplicatedException if the new title conflicts with an existing draft. The UpdateDraft handler also implements logic to delete and recreate a draft entity if its ID changes due to a title update, ensuring data consistency.
src/Blogger.Application/Articles/MakeDraft, src/Blogger.Application/Articles/UpdateDraft · high confidence
Centralized endpoint tag definitions
A new EndpointSchema class has been introduced to centralize the string constants used for API endpoint tagging. This change defines specific tags for Articles, Comments, and Subscribers, providing a single source of truth for these identifiers within the Blogger.APIs.Endpoints namespace.
src/Blogger.APIs/Endpoints · high confidence
Create Article command now requires tags and validates for duplicates
The Create Article application feature has been restructured into a dedicated folder and now enforces stricter input and validation. The command handler requires a list of tags to be passed when creating an article, and it checks for existing articles by ID before saving; if a duplicate is detected, it throws a specific exception to signal the conflict to the client.
src/Blogger.Application/Articles/CreateArticle · high confidence
Global error handling returns structured ProblemDetails
The API now uses a global exception handler to intercept unhandled exceptions and return standardized ProblemDetails responses. Domain exceptions are mapped to HTTP 400 Bad Request with the exception message included in the detail field, while all other exceptions result in HTTP 500 Internal Server Error with a generic error message.
src/Blogger.APIs/ErrorHandling · high confidence
Introduce comment and reply domain model with approval workflow
The CommentAggregate now defines the core domain entities for user comments and nested replies, including the Client value object for author details and ApproveLink for moderation. Comments and replies are created in an unapproved state and require explicit approval via ApproveLink tokens before they become visible; attempting to reply to an unapproved comment throws an UnapprovedCommentException. The aggregate exposes methods to approve comments and replies, raises a MakeCommentEvent upon creation, and is supported by an ICommentRepository interface for persistence.
src/Blogger.Domain/CommentAggregate · high confidence
Subscriber subscription logic and duplicate handling
The application layer now includes a dedicated command handler for the subscribe feature. When a user attempts to subscribe, the system checks for existing subscriptions using the subscriber service; if a duplicate is detected, it throws a specific exception that results in a 400 Bad Request response to the client. Otherwise, the new subscriber is created and persisted via the repository.
src/Blogger.Application/Subscribers/Subscribe · high confidence
Test coverage
Added EF Core database test fixtures for integration testing; Added empty load testing scripts; Added functional tests for article API endpoints; Added global usings for unit test project; Added integration tests for article command and query handlers; Added integration tests for comment and subscriber workflows; Added unit tests for core domain building blocks; Added unit tests for domain aggregates.
Dependencies
Enable centralized NuGet package management
The project now uses centralized package version management via a new Directory.Packages.props file, which defines specific versions for all NuGet packages (including EF Core 8.0.6, MediatR 12.2.0, Mapster 7.4.0, and xUnit 2.7.0). Individual project files (.csproj) have been updated to reference packages without version numbers, relying on this central configuration to ensure consistent dependency versions across the solution.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.
Score
- CAI 47 → 46 (-1.1)
- Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 94 → 94 (+0.3)
- Architecture 87 → 87 (+0.0)
- Maturity 52 → 52 (+0.0)
- Readiness 56 → 56 (+0.3)
- Security 29 → 27 (-2.6)
- Domain Modelling 95 → 98 (+2.7)
Resolved (14)
- Boundary-crossing change coupling: GetArticlesEndpoint.cs ↔ ArticleRepository.cs (src/Blogger.APIs/Endpoints/Articles/GetArticles/GetArticlesEndpoint.cs)
- Bounded contexts not declared
- Duplicated block (15 lines × 3) (src/Blogger.APIs/Endpoints/Articles/CreateArticle/CreateArticleRequestValidator.cs)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Inconsistent naming for request models: some use 'Request', some use 'RequestModel' or 'Commet' (typo). Specifically, 'MakeCommetRequest' has a typo, and 'ReplyToCommentRequestModel' uses 'Model' suffix while others use 'Request'.
- Inconsistent spelling of 'Subscription' in exception names: 'Subscribtion' (typo) vs 'Duplicated' (correct). Also, the exception for duplicate subscription is misspelled.
- No exposed public API
- Off-boarding risk: anonymized user #1
- Typo in endpoint name: 'Commet' instead of 'Comment' in the namespace/endpoint path.
- redundant comment (src/Blogger.Infrastructure/GlobalSuppressions.cs)
- redundant comment (tests/Blogger.FunctionalTests/Articles/ArticleApisTests.cs)
New (37)
- Change coupling: CreateArticleCommandHandler.cs ↔ MakingDraftCommandHandler.cs (src/Blogger.Application/Articles/CreateArticle/CreateArticleCommandHandler.cs)
- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- Duplicated block (16 lines × 3) (src/Blogger.APIs/Endpoints/Articles/CreateArticle/CreateArticleRequestValidator.cs)
- Duplicated block (39 lines × 2) (src/Blogger.Infrastructure/Persistence/Configurations/CommentConfiguration.cs)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- High: security finding (details withheld)
- Inconsistent grammar and spelling in test method names. One test uses 'should_be_have' (grammatically incorrect) and the other uses 'diffrent' (spelling error). While these are distinct tests, the presence of basic spelling/grammar errors indicates a lack of consistency in test naming hygiene.
- Inconsistent naming and typo in the MakeComment endpoint. The request parameter is named 'MakeCommetRequest' (typo: 'Commet'), while the application command is correctly named 'MakeCommentCommand'.
- Inconsistent naming for the request model in the ReplyToComment endpoint. One symbol uses 'RequestModel' while another uses 'Request'. Additionally, the namespace/endpoint folder name contains a typo 'ReplyToCommet' (missing 'n') in both instances.
- Inconsistent spelling in test method names. One test uses 'Pushlish' (typo for 'Publish'), while the other correctly uses 'Publish'.
- Inconsistent spelling in test method names. One test uses 'diffrent' (typo) while the other correctly uses 'different'.
- Inconsistent spelling of 'Subscription'. One exception uses 'Subscribtion' (typo), while the other uses 'Duplicated' (adjective) vs 'Duplicate' (noun/adjective) in naming conventions. Specifically, 'DuplicateSubscribtionException' contains a spelling error.
- Low coverage: src/Blogger.APIs/Endpoints/Articles/CreateArticle/CreateArticleRequestValidator.cs (src/Blogger.APIs/Endpoints/Articles/CreateArticle/CreateArticleRequestValidator.cs)
- Low coverage: src/Blogger.APIs/Endpoints/Articles/GetArticle/GetArticleRequestValidator.cs (src/Blogger.APIs/Endpoints/Articles/GetArticle/GetArticleRequestValidator.cs)
- Low coverage: src/Blogger.APIs/Endpoints/Articles/PublishDraft/PublishDraftRequestValidator.cs (src/Blogger.APIs/Endpoints/Articles/PublishDraft/PublishDraftRequestValidator.cs)
- Low coverage: src/Blogger.APIs/Endpoints/Comments/ApproveComment/ApproveCommentRequestValidator.cs (src/Blogger.APIs/Endpoints/Comments/ApproveComment/ApproveCommentRequestValidator.cs)
- Low coverage: src/Blogger.APIs/Endpoints/Comments/ApproveReply/ApproveReplyRequestValidator.cs (src/Blogger.APIs/Endpoints/Comments/ApproveReply/ApproveReplyRequestValidator.cs)
- …and 17 more
API surface
- Unchanged — 18 HTTP endpoints
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
thisisnabi/Blogger was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 20 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 21e54874c55ddd99816498b07454b7fdcd97d346 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-28e75b8e3254.