| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Full-stack .NET online book store application with event-sourced backend API and Blazor frontend, orchestrated by Aspire.
This project is a demonstration and exploration of modern .NET technologies, designed to be as complete as possible while strictly following architectural best practices, and keeping performance and scalability as core priorities.
I am sure a lot may be improved. Opening this code to the public is an opportunity to get feedback and learn from others' contributions.
A complete book store management system featuring:
"A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system."
— John Gall
This project deliberately moves away from the "microservices-first" dogma, instead embracing a Modular Monolith approach.
There is a growing industry consensus that starting with microservices introduces accidental complexity—distributed transactions, network latency, and infrastructure overhead—before domain boundaries are strictly defined. This solution provides a concrete example of how to build a scalable, robust system without the premature complexity of a distributed mesh.
The architecture emphasizes:
Modularity: Loose coupling is enforced using Event Sourcing and CQRS. Features communicate via messages (Wolverine), ensuring that future decomposition into services is a seamless refactoring rather than a rewrite.
Pragmatism & Performance: We prioritize clean, maintainable code over academic purity. By avoiding excessive abstraction layers (like generic repositories and passthrough services), we eliminate "architectural tax," ensuring the code remains easy to refactor and runs with maximum performance.
Completeness: Unlike typical "Hello World" demos, this project implements production-grade requirements: resiliency, distributed tracing, structured logging, correct HTTP semantics, optimistic concurrency, hybrid caching, configuration validation, content localization, scalable real-time updates, passwordless authentication, comprehensive testing, and trigram‑based search for fast, flexible text matching.
Simplicity: By keeping the deployment unit single but the code modular, we gain the benefits of microservices (isolation, maintainability) without the operational drawbacks.
This serves as a foundational blueprint that scales with your needs, allowing you to evolve from a simple, working system into a complex one naturally.
# Prerequisites: .NET 10 SDK, Aspire CLI, Docker Desktop
# Install Aspire CLI: Follow instructions at https://aspire.dev/get-started/install-cli/
# Clone and run
# HTTPS
git clone https://github.com/aalmada/BookStore.git
# OR SSH
git clone git@github.com:aalmada/BookStore.git
cd BookStore
dotnet restore
aspire runThe Aspire dashboard opens automatically, providing access to:
The project includes a custom Roslyn Analyzer (BookStore.ApiService.Analyzers) that enforces Event Sourcing, CQRS, and DDD patterns:
See Analyzers | Custom Roslyn analyzers to enforce architectural rules and prevent common mistakes. |Scalar UI
See the Project Structure guide for a detailed breakdown of the solution.
Authentication:
Passkey (Passwordless):
Account Management:
Note
Admin endpoints require authentication with the Admin role. Include the JWT token in the Authorization: Bearer <token> header.
# Get categories in Portuguese
curl -H "Accept-Language: pt-PT" http://localhost:5000/api/categories
# Create category with translations
curl -X POST http://localhost:5000/api/admin/categories \
-H "Content-Type: application/json" \
-d '{
"name": "Software Architecture",
"translations": {
"en": {"name": "Software Architecture"},
"pt": {"name": "Arquitetura de Software"}
}
}'# All operations create events in the event store
# Create a book
curl -X POST http://localhost:5000/api/admin/books \
-H "X-Correlation-ID: workflow-123" \
-d '{"title": "Clean Code", ...}'
# → BookAdded event stored
# Update the book
curl -X PUT http://localhost:5000/api/admin/books/{id} \
-H "X-Correlation-ID: workflow-123" \
-H "If-Match: \"1\"" \
-d '{"title": "Clean Code (Updated)", ...}'
# → BookUpdated event stored
# View all events for this workflow
SELECT * FROM mt_events
WHERE correlation_id = 'workflow-123';# Get book (receives ETag)
curl -i http://localhost:5000/api/books/{id}
# ETag: "5"
# Update with concurrency check
curl -X PUT http://localhost:5000/api/admin/books/{id} \
-H "If-Match: \"5\"" \
-d '{"title": "Updated Title", ...}'
# Success → ETag: "6"
# Concurrent update fails
curl -X PUT http://localhost:5000/api/admin/books/{id} \
-H "If-Match: \"5\"" \
-d '{"title": "Another Update", ...}'
# Error: 412 Precondition FailedThe project uses TUnit, a modern testing framework with built-in code coverage and parallel execution.
# Run all tests
dotnet test
# Run tests for specific project
dotnet test --project tests/ApiService/BookStore.ApiService.UnitTests/BookStore.ApiService.UnitTests.csproj
# Alternative: Run tests directly
dotnet run --project tests/ApiService/BookStore.ApiService.UnitTests/BookStore.ApiService.UnitTests.csprojNote
TUnit uses Microsoft.Testing.Platform on .NET 10+. The global.json file configures the test runner automatically.
This project is licensed under the MIT License.
Copyright (c) 2025 Antao Almada
Contributions are welcome! Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
By contributing, you agree that your contributions will be licensed under the MIT License.
| Back | FazBrowse Home | New Git URL |