# taylorleprechaun/cardcollector architecture

> Architecture diagram of the GitHub repository taylorleprechaun/cardcollector, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-11). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/taylorleprechaun/cardcollector
- Repository: https://github.com/taylorleprechaun/cardcollector

## Overview

#### Purpose and Entry Points
Card Collector is a personal Yu-Gi-Oh collection and purchase-planning system built as an ASP.NET Core Razor Pages application. HTTP startup, dependency wiring, authentication, EF Core setup, and hosted work begin in `Program.cs`. Feature endpoints are PageModels paired with server-rendered Razor views, e.g. `Pages/Collection.cshtml.cs`, `Pages/Wishlist.cshtml.cs`, and `Pages/Stats.cshtml.cs`.

#### Presentation and Interaction Layer
Razor Pages own request handling, form actions, redirects, CSV downloads, and page-specific view-model assembly. Shared partials provide reusable result tables and modals. Browser-side JavaScript augments selected workflows rather than serving as a separate frontend.
- `Pages/Browse.cshtml.cs`
- `Pages/Cart.cshtml.cs`
- `Pages/Shared/_Layout.cshtml`
- `wwwroot/js/cart.js`

#### Application Orchestration
`CardService` is the primary domain-facing read/orchestration layer. It joins cached card catalog data with persisted collection state to produce browsing, collection, wishlist, dashboard, audit, new-printing, and purchase-priority views. PageModels should cross this boundary through `ICardService`, rather than directly composing catalog and collection data.
- `Services/CardService.cs`
- `Services/ICardService.cs`
- `Services/PurchasePriorityAnalyzer.cs`

#### Catalog Ingestion and External Data Boundary
Card catalog metadata is represented by DTOs and loaded via a repository/cache boundary. Startup or cache refresh obtains yaml-yugi card/set data; image metadata comes from YGO Pro Deck, while images remain CDN-hosted. Cache behavior supports TTLs and stale-data fallback; Speed Duel sets are filtered during load.
- `Repository/CardDataRepository.cs`
- `Repository/CardDataMapper.cs`
- `Data/FileCacheHelper.cs`
- `DTO/YamlYugi/YamlCard.cs`

#### Persistence and Transaction Boundary
EF Core maps local SQLite state through `AppDbContext`. Repositories isolate entity-specific queries and mutations; `UnitOfWork` provides the commit boundary. Persisted state covers owned entries, preferred printings, cart/pending orders, checkouts, ignored/dismissed cards, and historical value snapshots.
- `Data/AppDbContext.cs`
- `Repository/UnitOfWork.cs`
- `Repository/CollectionRepository.cs`
- `Data/Models/CollectionEntry.cs`

#### Collection-to-Purchase Lifecycle
Users select preferred versions, which drive wishlist and buy-list candidates. Wishlist items can be staged as pending order lines, finalized through Cart into Orders, then received into the collection. Ownership, pending orders, and checkout state influence visibility and badges throughout shopping and collection workflows.
- `Pages/Wishlist.cshtml.cs`
- `Pages/BuyList.cshtml.cs`
- `Pages/Cart.cshtml.cs`
- `Repository/PendingOrderRepository.cs`

#### Pricing, Snapshots, and Analytics
`PricingService` fetches live per-card pricing from the YGO Pro Deck pricing endpoint. `PricingDataCache` avoids repeated retrieval, while the hosted background service runs nightly at midnight US Eastern to price owned/wishlisted cards, write dated value snapshots, and prune history. Dashboard and Stats consume persisted snapshots rather than requiring live pricing per request.
- `Services/PricingService.cs`
- `Services/PricingDataCache.cs`
- `Services/PriceRefreshBackgroundService.cs`
- `Repository/ValueSnapshotRepository.cs`

#### Runtime and Deployment
The system targets .NET 10 with EF Core 9, SQLite, Newtonsoft.Json, cookie authentication backed by BCrypt credentials, Bootstrap, and CDN Chart.js. Deployment is automated through GitHub Actions and a PowerShell/service-unit deployment path.
- `CardCollector.csproj`
- `appsettings.json`
- `.github/workflows/deploy.yml`
- `scripts/card-collector.service`

Main entry points: [`Services/CardService.cs`](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/CardService.cs) (CardService), [`Services/PriceRefreshBackgroundService.cs`](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PriceRefreshBackgroundService.cs) (Nightly price refresh), [`Data/AppDbContext.cs`](https://github.com/taylorleprechaun/cardcollector/blob/main/Data/AppDbContext.cs) (AppDbContext), [`Pages/Collection.cshtml.cs`](https://github.com/taylorleprechaun/cardcollector/blob/main/Pages/Collection.cshtml.cs) (Razor PageModels)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web UI"]
  node_pages["Razor PageModels<br/>HTTP endpoints"]
  node_layout["Shared Razor layout<br/>server-rendered views<br/>[_Layout.cshtml]"]
  node_cart_js["Cart browser script<br/>browser enhancement<br/>[cart.js]"]
end

subgraph group_application["Application services"]
  node_card_service_interface["ICardService<br/>application boundary<br/>[ICardService.cs]"]
  node_card_service["CardService<br/>read orchestration<br/>[CardService.cs]"]
  node_priority_analyzer["Purchase priority analyzer<br/>domain analysis"]
end

subgraph group_catalog["Catalog data"]
  node_catalog_repository["Card data repository<br/>catalog repository"]
  node_catalog_mapper["Card data mapper<br/>catalog mapping<br/>[CardDataMapper.cs]"]
  node_file_cache[("File cache helper<br/>cache storage<br/>[FileCacheHelper.cs]")]
  node_yaml_card["YamlCard DTO<br/>external catalog DTO<br/>[YamlCard.cs]"]
end

subgraph group_persistence["Local state"]
  node_db_context[("AppDbContext<br/>EF Core context<br/>[AppDbContext.cs]")]
  node_unit_of_work["Unit of work<br/>transaction boundary<br/>[UnitOfWork.cs]"]
  node_collection_repository["Collection repository<br/>state repository"]
  node_pending_orders["Pending order repository<br/>shopping state repository"]
  node_collection_entry["Collection entry<br/>EF entity<br/>[CollectionEntry.cs]"]
end

subgraph group_pricing["Pricing and analytics"]
  node_pricing_service["Pricing service<br/>live pricing client<br/>[PricingService.cs]"]
  node_pricing_cache[("Pricing data cache<br/>pricing cache")]
  node_price_refresh_worker["Nightly price refresh<br/>hosted background service"]
  node_value_snapshots["Value snapshot repository<br/>analytics repository"]
end

node_startup{{"ASP.NET startup<br/>composition root<br/>[Program.cs]"}}

node_startup -->|"hosts"| node_pages
node_startup -->|"configures"| node_db_context
node_startup -->|"starts"| node_price_refresh_worker
node_pages -->|"renders in"| node_layout
node_cart_js -->|"augments cart actions"| node_pages
node_pages -->|"queries via"| node_card_service_interface
node_card_service_interface -->|"implemented by"| node_card_service
node_card_service -->|"reads catalog"| node_catalog_repository
node_card_service -->|"joins collection state"| node_collection_repository
node_card_service -->|"uses shopping state"| node_pending_orders
node_card_service -->|"calculates priorities"| node_priority_analyzer
node_catalog_repository -->|"maps"| node_catalog_mapper
node_catalog_mapper -->|"transforms"| node_yaml_card
node_catalog_repository -->|"caches catalog"| node_file_cache
node_collection_repository -->|"queries and mutates"| node_db_context
node_collection_repository -->|"manages"| node_collection_entry
node_pending_orders -->|"queries and mutates"| node_db_context
node_unit_of_work -->|"commits through"| node_db_context
node_price_refresh_worker -->|"requests prices"| node_pricing_service
node_pricing_service -->|"uses"| node_pricing_cache
node_price_refresh_worker -->|"selects owned cards"| node_collection_repository
node_price_refresh_worker -->|"selects wishlisted cards"| node_pending_orders
node_price_refresh_worker -->|"writes snapshots"| node_value_snapshots
node_value_snapshots -->|"persists in"| node_db_context
node_card_service -->|"reads analytics"| node_value_snapshots

click node_startup "https://github.com/taylorleprechaun/cardcollector/blob/main/Program.cs"
click node_pages "https://github.com/taylorleprechaun/cardcollector/blob/main/Pages/Collection.cshtml.cs"
click node_layout "https://github.com/taylorleprechaun/cardcollector/blob/main/Pages/Shared/_Layout.cshtml"
click node_cart_js "https://github.com/taylorleprechaun/cardcollector/blob/main/wwwroot/js/cart.js"
click node_card_service_interface "https://github.com/taylorleprechaun/cardcollector/blob/main/Services/ICardService.cs"
click node_card_service "https://github.com/taylorleprechaun/cardcollector/blob/main/Services/CardService.cs"
click node_priority_analyzer "https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PurchasePriorityAnalyzer.cs"
click node_catalog_repository "https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/CardDataRepository.cs"
click node_catalog_mapper "https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/CardDataMapper.cs"
click node_file_cache "https://github.com/taylorleprechaun/cardcollector/blob/main/Data/FileCacheHelper.cs"
click node_yaml_card "https://github.com/taylorleprechaun/cardcollector/blob/main/DTO/YamlYugi/YamlCard.cs"
click node_db_context "https://github.com/taylorleprechaun/cardcollector/blob/main/Data/AppDbContext.cs"
click node_unit_of_work "https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/UnitOfWork.cs"
click node_collection_repository "https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/CollectionRepository.cs"
click node_pending_orders "https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/PendingOrderRepository.cs"
click node_collection_entry "https://github.com/taylorleprechaun/cardcollector/blob/main/Data/Models/CollectionEntry.cs"
click node_pricing_service "https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PricingService.cs"
click node_pricing_cache "https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PricingDataCache.cs"
click node_price_refresh_worker "https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PriceRefreshBackgroundService.cs"
click node_value_snapshots "https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/ValueSnapshotRepository.cs"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_pages,node_layout,node_cart_js toneBlue
class node_card_service_interface,node_card_service,node_priority_analyzer toneAmber
class node_catalog_repository,node_catalog_mapper,node_file_cache,node_yaml_card toneMint
class node_db_context,node_unit_of_work,node_collection_repository,node_pending_orders,node_collection_entry toneRose
class node_pricing_service,node_pricing_cache,node_price_refresh_worker,node_value_snapshots toneIndigo
class node_startup toneNeutral
```

## Components

### Web UI

- [Razor PageModels](https://github.com/taylorleprechaun/cardcollector/blob/main/Pages/Collection.cshtml.cs): HTTP endpoints · Handles collection, wishlist, stats, browse, cart, and buy-list requests. · `Pages/Collection.cshtml.cs`
- [Shared Razor layout](https://github.com/taylorleprechaun/cardcollector/blob/main/Pages/Shared/_Layout.cshtml): server-rendered views · `Pages/Shared/_Layout.cshtml`
- [Cart browser script](https://github.com/taylorleprechaun/cardcollector/blob/main/wwwroot/js/cart.js): browser enhancement · `wwwroot/js/cart.js`

### Application services

- [ICardService](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/ICardService.cs): application boundary · PageModels use this boundary for catalog-plus-state views. · `Services/ICardService.cs`
- [CardService](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/CardService.cs): read orchestration · Combines cached catalog data with collection state for application views. · `Services/CardService.cs`
- [Purchase priority analyzer](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PurchasePriorityAnalyzer.cs): domain analysis · `Services/PurchasePriorityAnalyzer.cs`

### Catalog data

- [Card data repository](https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/CardDataRepository.cs): catalog repository · Loads filtered yaml-yugi catalog and image metadata through cache-backed sources. · `Repository/CardDataRepository.cs`
- [Card data mapper](https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/CardDataMapper.cs): catalog mapping · `Repository/CardDataMapper.cs`
- [File cache helper](https://github.com/taylorleprechaun/cardcollector/blob/main/Data/FileCacheHelper.cs): cache storage · Supports TTLs and stale-data fallback. · `Data/FileCacheHelper.cs`
- [YamlCard DTO](https://github.com/taylorleprechaun/cardcollector/blob/main/DTO/YamlYugi/YamlCard.cs): external catalog DTO · `DTO/YamlYugi/YamlCard.cs`

### Local state

- [AppDbContext](https://github.com/taylorleprechaun/cardcollector/blob/main/Data/AppDbContext.cs): EF Core context · Maps local SQLite collection, order, preference, and snapshot state. · `Data/AppDbContext.cs`
- [Unit of work](https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/UnitOfWork.cs): transaction boundary · Commits repository mutations. · `Repository/UnitOfWork.cs`
- [Collection repository](https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/CollectionRepository.cs): state repository · `Repository/CollectionRepository.cs`
- [Pending order repository](https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/PendingOrderRepository.cs): shopping state repository · Stages wishlist candidates through checkout and receipt. · `Repository/PendingOrderRepository.cs`
- [Collection entry](https://github.com/taylorleprechaun/cardcollector/blob/main/Data/Models/CollectionEntry.cs): EF entity · `Data/Models/CollectionEntry.cs`

### Pricing and analytics

- [Pricing service](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PricingService.cs): live pricing client · Fetches per-card pricing from YGO Pro Deck. · `Services/PricingService.cs`
- [Pricing data cache](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PricingDataCache.cs): pricing cache · Avoids repeated live price retrieval. · `Services/PricingDataCache.cs`
- [Nightly price refresh](https://github.com/taylorleprechaun/cardcollector/blob/main/Services/PriceRefreshBackgroundService.cs): hosted background service · Prices owned and wishlisted cards, writes snapshots, and prunes history. · `Services/PriceRefreshBackgroundService.cs`
- [Value snapshot repository](https://github.com/taylorleprechaun/cardcollector/blob/main/Repository/ValueSnapshotRepository.cs): analytics repository · Persists dated collection values for dashboard and stats. · `Repository/ValueSnapshotRepository.cs`

### Other components

- [ASP.NET startup](https://github.com/taylorleprechaun/cardcollector/blob/main/Program.cs): composition root · Configures HTTP, authentication, EF Core, DI, and hosted work. · `Program.cs`

## Connections

- ASP.NET startup → Razor PageModels: hosts
- ASP.NET startup → AppDbContext: configures
- ASP.NET startup → Nightly price refresh: starts
- Razor PageModels → Shared Razor layout: renders in
- Cart browser script → Razor PageModels: augments cart actions
- Razor PageModels → ICardService: queries via
- ICardService → CardService: implemented by
- CardService → Card data repository: reads catalog
- CardService → Collection repository: joins collection state
- CardService → Pending order repository: uses shopping state
- CardService → Purchase priority analyzer: calculates priorities
- Card data repository → Card data mapper: maps
- Card data mapper → YamlCard DTO: transforms
- Card data repository → File cache helper: caches catalog
- Collection repository → AppDbContext: queries and mutates
- Collection repository → Collection entry: manages
- Pending order repository → AppDbContext: queries and mutates
- Unit of work → AppDbContext: commits through
- Nightly price refresh → Pricing service: requests prices
- Pricing service → Pricing data cache: uses
- Nightly price refresh → Collection repository: selects owned cards
- Nightly price refresh → Pending order repository: selects wishlisted cards
- Nightly price refresh → Value snapshot repository: writes snapshots
- Value snapshot repository → AppDbContext: persists in
- CardService → Value snapshot repository: reads analytics
