As a home project and learning experience I am building a web app to run locally on my PC to track my trading card collections. This will also include tracking deck construction, wish lists, and hopefully collection/deck values. The goal is to eventually incorporate cards from the following games: --Magic the Gathering --Star Wars Unlimited --Disney Lorcana --Flesh and Blood --Star Wars CCG --Guardians --Dicemasters
- .NET SDK: 9.0 (pinned via
global.json) - Node.js: 20+ (for Vite client)
- Entity Framework Core: 9.0.14 (Sqlite provider, design, and tools packages)
From the repository root:
dotnet restore ./api/api.csproj
dotnet build ./api/api.csproj
dotnet run --project ./api/api.csproj --launch-profile "TradingCardApi (HTTPS)"The API will run on https://localhost:7226 and http://localhost:5229.
To verify the API is running, access the health endpoint:
curl -k https://localhost:7226/api/healthFrom the client-vite directory:
npm install # or pnpm install
npm run dev # or pnpm devThe Vite dev server will run on http://localhost:5173.
Create a .env.local file in the client-vite directory (already gitignored):
# Point directly to the API server (recommended - no proxy)
VITE_API_BASE=https://localhost:7226/apiThis configures the client to make requests directly to the API server. Alternatively, you can copy the provided .env.example file:
cd client-vite
cp .env.example .env.localTo verify the API is reachable, access the health endpoint:
curl -k https://localhost:7226/api/health- In production (or any deployed environment), provide a 256-bit or longer signing key via the
JWT__KEYenvironment variable. The API refuses to start if the key is missing or too short. - For local development you can optionally store a key with
dotnet user-secrets:When no key is supplied in Development/Testing the API falls back to a deterministic development key and logs a warning on startup.dotnet user-secrets set "Jwt:Key" "DevOnly_Minimum_32_Chars_Key_For_Local_Use_1234" --project ./api/api.csproj
- Ensure you are in the
apidirectory, then rundotnet run seedto populate the SQLite database with three sample games and sets for UI testing. The command runs migrations first, skips if any cards already exist, and exits without starting the web server.
GET /api/health– returns a simple health check status to verify API connectivity.GET /api/cards/{id}/printings– returns the available printings for a card, ordered by set and collector number.GET /api/cards/{id}/sparkline?days=30– returns aggregated value points for the card across its non-proxy printings.GET /api/collection/value/history?days=90– produces daily totals for the authenticated user's collection with proxies excluded.GET /api/decks/{deckId}/value/history?days=90– surfaces daily deck values across owned printings with proxies excluded.POST /api/collection/items– quick-add endpoint that increments the owned quantity for the authenticated user.POST /api/wishlist/items– quick-add endpoint that increments the desired quantity for the authenticated user.
[RequireAdmin]enforces administrator access based on the authenticated JWT principal and returns a403problem response otherwise./api/admin/usersexposes admin-only CRUD operations for users with optimistic UI support in the Vite client. The API prevents demoting or deleting the final administrator and returns a409 Conflictproblem response when that safeguard triggers./api/admin/prices/ingestingests per-printing price points and safely upserts duplicates based on(cardPrintingId, capturedAt).