Thank you for your interest in contributing to the Book Store project! This document provides guidelines and instructions for contributing.
- Be respectful and inclusive
- Welcome newcomers and help them get started
- Focus on constructive feedback
- Respect differing viewpoints and experiences
Before creating an issue:
- Search existing issues to avoid duplicates
- Use a clear title that describes the problem
- Provide details:
- Steps to reproduce
- Expected vs actual behavior
- Environment (OS, .NET version, Docker version)
- Relevant logs from Aspire dashboard
Feature requests are welcome! Please:
- Check existing issues for similar requests
- Describe the use case - why is this feature needed?
- Provide examples of how it would work
- Consider the scope - does it fit the project goals?
- Fork the repository and create your branch from
main. - Write or update tests for your changes (see below).
- Run all tests locally and ensure they pass.
- Format your code: Run
dotnet formatand resolve any issues. - Open a PR against
mainwith a clear title and description. - Link related issues in your PR description, if applicable.
- Wait for review: At least one team member must approve before merging.
- Address feedback promptly and push updates to your branch.
- Do not merge your own PR unless you have explicit approval.
Requirements: .NET 10 SDK with C# 14, Docker Desktop
# Clone your fork
git clone https://github.com/YOUR_USERNAME/BookStore.git
cd BookStore
dotnet restore
# (Optional) Install Aspire CLI: https://aspire.dev/get-started/install-cli/
aspire runNote: The project uses the new .slnx solution file format introduced in .NET 10.
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes following the coding standards
-
Write tests for new functionality
-
Run tests to ensure nothing breaks (see below for details):
dotnet test -
Update documentation if needed
-
Commit with clear messages:
git commit -m "feat: add book rating feature"
Follow Conventional Commits:
feat:- New featurefix:- Bug fixdocs:- Documentation changesstyle:- Code style changes (formatting, etc.)refactor:- Code refactoringtest:- Adding or updating testschore:- Maintenance tasks
Examples:
feat: add book rating endpoint
fix: correct ETag validation in update handler
docs: update getting-started guide
refactor: simplify book search projection
- Follow the BookStore conventions and
.editorconfig. - Use
[LoggerMessage(...)]for all logging—never useConsole.WriteLineor direct logger calls. - Use the Result pattern for error handling.
- Business logic belongs in handlers/aggregates, not endpoints.
- Add/verify tests for all new features and bug fixes.
- Ensure cache invalidation and SSE notifications are handled where relevant.
- Keep PRs focused and small; large or multi-purpose PRs may be asked to split.
- Be respectful and constructive in review comments.
- Automated Checks: PRs must pass CI (build, lint, and tests).
- Code Review: At least one team member must review and approve before merging.
- Feedback: Address all review comments. Push updates to the same branch.
- No Direct Merges: Never merge your own PR without review.
- Commit Messages: Use clear, descriptive commit messages. Squash if appropriate.
-
Push to your fork:
git push origin feature/your-feature-name
-
Create a Pull Request with:
- Clear title and description
- Reference to related issues
- Screenshots (if UI changes)
- Test results
-
Respond to feedback from reviewers
-
Keep your PR updated with the main branch
Follow the project's .editorconfig - All C# coding standards are defined there and enforced by the IDE and build process.
Key conventions:
- Use meaningful names for variables, methods, and classes
- Add XML documentation for public APIs
- Keep methods small and focused (single responsibility)
- Use async/await for I/O operations
- Prefer records for immutable data
- Always use
DateTimeOffset.UtcNow(neverDateTime.Now) - Always use
Guid.CreateVersion7()(neverGuid.NewGuid())
Your IDE will automatically apply formatting rules from .editorconfig. Run dotnet build to see any style violations.
The project uses Roslynator.Analyzers (version 4.15.0) for enhanced code analysis:
- 500+ analyzers for code quality, style, and best practices
- Automatic refactorings suggested by your IDE
- Build-time enforcement - violations appear as warnings during build
- Modern C# patterns - Encourages collection expressions, pattern matching, etc.
Common Roslynator suggestions you'll see:
- Use collection expressions:
[]instead ofnew() - Simplify LINQ expressions
- Remove unnecessary code
- Use pattern matching where applicable
- Optimize string operations
The Directory.Build.props file at the root of the solution defines settings shared by all projects. This ensures consistency across the codebase.
Common configurations include:
- Build Settings:
TargetFramework(.NET 10),LangVersion(latest),Nullable(enable),ImplicitUsings. - Code Quality:
TreatWarningsAsErrors,EnforceCodeStyleInBuild, and analyzer settings. - Metadata:
AuthorsandCopyrightinformation. - Common Dependencies: Global package references like
Roslynator.AnalyzersandMicrosoft.SourceLink.GitHub.
All projects automatically inherit these settings, so you don't need to repeat them in individual .csproj files.
This project uses Central Package Management (CPM).
- Manage versions in
Directory.Packages.props: Do not specify versions in individual.csprojfiles unless necessary for a specific override. - Global Dependencies: Common dependencies (like Analyzers) defined in
Directory.Build.propsalso use versions fromDirectory.Packages.props. - Add packages normally:
dotnet add package <PackageName>will automatically updateDirectory.Packages.propsor the project file as needed (requires .NET 10 SDK or newer). - Check for updates: Use
dotnet outdatedto see available updates for all packages in the solution.
- Events are immutable - never modify event definitions
- Events are past tense -
BookAdded, notAddBook - Include timestamps - always use
DateTimeOffset.UtcNow - Use correlation IDs - for distributed tracing
- Use minimal APIs for endpoints
- Follow REST conventions for public endpoints
- Use command/handler pattern (Wolverine) for writes
- Return appropriate status codes
- Include ETag support for updates/deletes
- Add XML documentation for OpenAPI
- Write unit tests for handlers
- Use NSubstitute for mocking
- Test edge cases and error conditions
- Aim for high code coverage on business logic
- Use camelCase for property names
- Serialize enums as strings (not integers)
- Use ISO 8601 for dates (
DateTimeOffset) - Always use UTC timezone
Example:
{
"bookId": "018d5e4a-7b2c-7000-8000-123456789abc",
"title": "Clean Code",
"status": "active",
"lastModified": "2025-12-26T17:26:14.123+00:00"
}Understanding the architecture helps you contribute effectively:
- BookStore.ApiService - Backend API (event sourcing, CQRS)
- BookStore.Web - Blazor frontend
- BookStore.AppHost - Aspire orchestration
- BookStore.ServiceDefaults - Shared configuration
- BookStore.Shared - Shared library
- BookStore.Shared.Tests - Shared unit tests
- BookStore.ApiService.Tests - API unit tests
- BookStore.Web.Tests - Web tests
Key patterns:
- Event Sourcing - All state changes via events
- CQRS - Separate read/write models
- Command/Handler - Wolverine mediator pattern
- Projections - Async read model updates
When adding features, update:
- README.md - If it affects quick start or features
- docs/getting-started.md - If it changes setup
- docs/architecture.md - If it changes design
- XML comments - For all public APIs
- OpenAPI - Automatically generated from code
- Check the docs in the
/docsfolder - Open an issue for questions
- Review existing code for examples
By contributing, you agree that your contributions will be licensed under the same license as the project (see LICENSE).
Your contributions make this project better for everyone. We appreciate your time and effort! 🎉