11 KiB
Architecture
This document describes the active architecture of The Biergarten App.
High-Level Overview
The Biergarten App is a monorepo with a clear split between the backend and the active website:
- Backend: .NET 10 Web API with SQL Server and a layered architecture
- Frontend: React 19 + React Router 7 website in
src/Website - Architecture Style: Layered backend plus server-rendered React frontend
The legacy Next.js frontend has been retained in src/Website-v1 for reference only and is
documented in archive/legacy-website-v1.md.
Diagrams
For visual representations, see:
- architecture.svg - Layered architecture diagram
- deployment.svg - Docker deployment diagram
- authentication-flow.svg - Authentication workflow
- database-schema.svg - Database relationships
Backend Architecture
Layered Architecture Pattern
The backend follows a strict layered architecture:
┌─────────────────────────────────────┐
│ API Layer (Controllers) │
│ - HTTP Endpoints │
│ - Request/Response mapping │
│ - Swagger/OpenAPI │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Service Layer (Business Logic) │
│ - Authentication logic │
│ - User management │
│ - Validation & orchestration │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Infrastructure Layer (Tools) │
│ - JWT token generation │
│ - Password hashing (Argon2id) │
│ - Email services │
│ - Repository implementations │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Domain Layer (Entities) │
│ - UserAccount, UserCredential │
│ - Pure POCO classes │
│ - No external dependencies │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ Database (SQL Server) │
│ - Stored procedures │
│ - Tables & constraints │
└─────────────────────────────────────┘
Layer Responsibilities
API Layer (API.Core)
Purpose: HTTP interface and request handling
Components:
- Controllers (
AuthController,UserController) - Middleware for error handling
- Swagger/OpenAPI documentation
- Health check endpoints
Dependencies:
- Service layer
- ASP.NET Core framework
Rules:
- No business logic
- Only request/response transformation
- Delegates all work to Service layer
Service Layer (Service.Auth, Service.UserManagement)
Purpose: Business logic and orchestration
Components:
- Authentication services (login, registration)
- User management services
- Business rule validation
- Transaction coordination
Dependencies:
- Infrastructure layer (repositories, JWT, password hashing)
- Domain entities
Rules:
- Contains all business logic
- Coordinates multiple infrastructure components
- No direct database access (uses repositories)
- Returns domain models, not DTOs
Infrastructure Layer
Purpose: Technical capabilities and external integrations
Components:
- Infrastructure.Repository: Data access via stored procedures
- Infrastructure.Jwt: JWT token generation and validation
- Infrastructure.PasswordHashing: Argon2id password hashing
- Infrastructure.Email: Email sending capabilities
- Infrastructure.Email.Templates: Email template rendering
Dependencies:
- Domain entities
- External libraries (ADO.NET, JWT, Argon2, etc.)
Rules:
- Implements technical concerns
- No business logic
- Reusable across services
Domain Layer (Domain.Entities)
Purpose: Core business entities and models
Components:
UserAccount- User profile dataUserCredential- Authentication credentialsUserVerification- Account verification state
Dependencies:
- None (pure domain)
Rules:
- Plain Old CLR Objects (POCOs)
- No framework dependencies
- No infrastructure references
- Represents business concepts
Design Patterns
Repository Pattern
Purpose: Abstract database access behind interfaces
Implementation:
IAuthRepository- Authentication queriesIUserAccountRepository- User account queriesDefaultSqlConnectionFactory- Connection management
Benefits:
- Testable (easy to mock)
- SQL-first approach (stored procedures)
- Centralized data access logic
Example:
public interface IAuthRepository
{
Task<UserCredential> GetUserCredentialAsync(string username);
Task<int> CreateUserAccountAsync(UserAccount user, UserCredential credential);
}
Dependency Injection
Purpose: Loose coupling and testability
Configuration: Program.cs registers all services
Lifetimes:
- Scoped: Repositories, Services (per request)
- Singleton: Connection factories, JWT configuration
- Transient: Utilities, helpers
SQL-First Approach
Purpose: Leverage database capabilities
Strategy:
- All queries via stored procedures
- No ORM (Entity Framework not used)
- Database handles complex logic
- Application focuses on orchestration
Stored Procedure Examples:
USP_RegisterUser- User registrationUSP_GetUserAccountByUsername- User lookupUSP_RotateUserCredential- Password update
Frontend Architecture
Active Website (src/Website)
The current website is a React Router 7 application with server-side rendering enabled.
src/Website/
├── app/
│ ├── components/ Shared UI such as Navbar, FormField, SubmitButton, ToastProvider
│ ├── lib/ Auth helpers, schemas, and theme metadata
│ ├── routes/ Route modules for home, login, register, dashboard, confirm, theme
│ ├── root.tsx App shell and global providers
│ └── app.css Theme tokens and global styling
├── .storybook/ Storybook config and preview setup
├── stories/ Storybook stories for shared UI and themes
├── tests/playwright/ Storybook Playwright coverage
└── package.json Frontend scripts and dependencies
Frontend Responsibilities
- Render the auth demo and theme guide routes
- Manage cookie-backed website session state
- Call the .NET API for login, registration, token refresh, and confirmation
- Provide shared UI building blocks for forms, navigation, themes, and toasts
- Supply Storybook documentation and browser-based component verification
Theme System
The active website uses semantic DaisyUI theme tokens backed by four Biergarten themes:
- Biergarten Lager
- Biergarten Stout
- Biergarten Cassis
- Biergarten Weizen
All component styling should prefer semantic tokens such as primary, success,
surface, and highlight instead of hard-coded color values.
Legacy Frontend
The previous Next.js frontend has been archived at src/Website-v1. Active product and
engineering documentation should point to src/Website, while legacy notes live in
archive/legacy-website-v1.md.
Security Architecture
Authentication Flow
-
Registration:
- User submits credentials
- Password hashed with Argon2id
- User account created
- JWT token issued
-
Login:
- User submits credentials
- Password verified against hash
- JWT token issued
- Token stored client-side
-
API Requests:
- Client sends JWT in Authorization header
- Middleware validates token
- Request proceeds if valid
Password Security
Algorithm: Argon2id
- Memory: 64MB
- Iterations: 4
- Parallelism: CPU core count
- Salt: 128-bit (16 bytes)
- Hash: 256-bit (32 bytes)
JWT Tokens
Algorithm: HS256 (HMAC-SHA256)
Claims:
sub- User IDunique_name- Usernamejti- Unique token IDiat- Issued at timestampexp- Expiration timestamp
Configuration (appsettings.json):
{
"Jwt": {
"ExpirationMinutes": 60,
"Issuer": "biergarten-api",
"Audience": "biergarten-users"
}
}
Database Architecture
SQL-First Philosophy
Principles:
- Database is source of truth
- Complex queries in stored procedures
- Database handles referential integrity
- Application orchestrates, database executes
Benefits:
- Performance optimization via execution plans
- Centralized query logic
- Version-controlled schema (migrations)
- Easier query profiling and tuning
Migration Strategy
Tool: DbUp
Process:
- Write SQL migration script
- Embed in
Database.Migrationsproject - Run migrations on startup
- Idempotent and versioned
Migration Files:
scripts/
├── 001-CreateUserTables.sql
├── 002-CreateLocationTables.sql
├── 003-CreateBreweryTables.sql
└── ...
Data Seeding
Purpose: Populate development/test databases
Implementation: Database.Seed project
Seed Data:
- Countries, states/provinces, cities
- Test user accounts
- Sample breweries (future)
Deployment Architecture
Docker Containerization
Container Structure:
sqlserver- SQL Server 2022database.migrations- Schema migration runnerdatabase.seed- Data seederapi.core- ASP.NET Core Web API
Environments:
- Development (
docker-compose.dev.yaml) - Testing (
docker-compose.test.yaml) - Production (
docker-compose.prod.yaml)
For details, see Docker Guide.
Health Checks
SQL Server: Validates database connectivity API: Checks service health and dependencies
Configuration:
healthcheck:
test: ["CMD-SHELL", "sqlcmd health check"]
interval: 10s
retries: 12
start_period: 30s
Testing Architecture
Test Pyramid
┌──────────────┐
│ Integration │ ← API.Specs (Reqnroll)
│ Tests │
├──────────────┤
│ Unit Tests │ ← Service.Auth.Tests
│ (Service) │ Repository.Tests
├──────────────┤
│ Unit Tests │
│ (Repository) │
└──────────────┘
Strategy:
- Many unit tests (fast, isolated)
- Fewer integration tests (slower, e2e)
- Mock external dependencies
- Test database for integration tests
For details, see Testing Guide.