CardApp

A full-stack Pokemon Trading Card Game collection manager, price tracker, and trading platform. Browse the complete card catalog, manage your collection, trade with other collectors, track portfolio value with daily market prices, and run a vendor storefront.

Features

Card Catalog

  • Full-text search across card name, artist, flavor text, abilities, and attacks
  • Advanced filtering by set, type, rarity, supertype, subtype, and artist
  • Sorting by name, number, rarity, HP, release date, or market price
  • Artist browsing with aggregate collection and pricing stats
  • Infinite scroll pagination

Collection Management

  • Inventory tracking with per-card quantities and purchase prices
  • Portfolio valuation with per-card and total market value, gain/loss calculation
  • Wishlist for tracking cards you want
  • Tags for organizing your collection with color-coded labels
  • Bulk CSV import/export for managing large collections

Pricing & Alerts

  • Multi-source pricing from 7 sources (Scrydex, TCGdex, PokeTrace, PokemonPriceTracker, PriceCharting, TAG, PokemonAPI)
  • Price history charts with configurable date range
  • Price alerts when market prices change beyond your configured threshold
  • Exchange rate support for multi-currency display

Grading

  • Population data from grading services (PSA, CGC, TAG, ACE)
  • EV calculator for expected grading value analysis

Trading

  • Trade proposals between users with counter-offer flow
  • Real-time updates via SignalR when both parties are online
  • Atomic inventory transfer on trade acceptance
  • Trade notifications with unread count badge
  • Trade animation with Pokemon-inspired card swap effect

Vendor Features

  • Public storefront with custom pricing and shop branding
  • Custom pricing strategies (fixed, markup percent, markup flat)
  • Margin rules for automated pricing
  • Batch operations on inventory (update quantity, tag, delete)
  • Analytics dashboard with collection value trends and top cards

Authentication & Accounts

  • Passwordless auth via passkeys (WebAuthn/FIDO2), OAuth (Google, Microsoft, Discord), or magic link email
  • Cookie-based sessions (no client-side tokens)
  • Account linking to connect multiple sign-in methods
  • Role-based access (User, Vendor, Admin, Owner)

Admin

  • User management with role assignment
  • Price sync control panel for on-demand price fetching
  • Expense ledger for tracking operational costs
  • Rarity rank editor for custom rarity ordering

UI

  • Dark mode with Catppuccin Macchiato theme and light mode toggle
  • Responsive design with shadcn/ui components

Tech Stack

LayerTechnology
FrontendNext.js 16, React 19, Tailwind CSS 4, shadcn/ui, Recharts
BackendASP.NET Core 10, Entity Framework Core 10, SignalR
AuthASP.NET Identity, FIDO2 (passkeys), OAuth 2.0, magic links
DatabasePostgreSQL 15
Pricing7 price sources (Scrydex primary), daily CronJob
Card Datapokemon-tcg-data (git submodule, ~15,000+ cards)
EmailPostfix (SMTP)
InfrastructureKubernetes, Terraform, Traefik, Keel (auto-deploy)
CI/CDGitHub Actions, GitHub Container Registry

Project Structure

CardApp/
├── backend/              # ASP.NET Core API
│   ├── CardApp.Api/      #   Controllers, models, services, migrations
│   └── CardApp.Api.Tests/ #  xUnit tests
├── frontend/             # Next.js app
│   └── src/
│       ├── app/          #   Pages (19 routes)
│       ├── components/   #   UI components (27+)
│       ├── contexts/     #   Auth and currency contexts
│       ├── hooks/        #   Custom React hooks
│       ├── lib/          #   API client, passkey helper, utilities
│       └── types/        #   TypeScript DTOs
├── data/                 # pokemon-tcg-data submodule (card/set JSON)
├── infra/                # Terraform (K8s deployments, Helm, ingress)
└── docs/                 # Documentation

Getting Started

Prerequisites

Clone

git clone --recurse-submodules https://github.com/matt-edmondson/CardApp.git
cd CardApp

If you already cloned without submodules:

git submodule update --init --recursive

Database

Start a PostgreSQL instance. The simplest way with Docker:

docker run -d --name cardapp-db \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=cardapp \
  -p 5432:5432 \
  postgres:15

The backend auto-runs EF Core migrations on startup, so no manual migration step is needed.

Backend

cd backend/CardApp.Api
dotnet restore
dotnet run

Runs on http://localhost:5000. Uses appsettings.Development.json which connects to localhost:5432 with postgres/postgres credentials by default.

Frontend

cd frontend
npm install
npm run dev

Runs on http://localhost:3000. Create a .env.local file if one doesn't exist:

NEXT_PUBLIC_API_URL=http://localhost:5000

Price Fetching (Optional)

Fetch market prices from Scrydex:

cd backend/CardApp.Api
SCRYDEX_API_KEY=your_key SCRYDEX_TEAM_ID=your_team dotnet run -- --price-fetch

Fetch specific sets only:

PRICE_FETCH_SETS="sv01,sv02" dotnet run -- --price-fetch

Deployment

The app deploys to Kubernetes via Terraform. See infra/ for the full configuration.

Key resources:

  • Backend and frontend deployments with GHCR images
  • PostgreSQL via Bitnami Helm chart
  • Traefik IngressRoute with TLS
  • Postfix for magic link email delivery
  • CronJob for daily price fetching (6 AM UTC)
  • Keel for automatic deployment on new image pushes
cd infra
cp terraform.tfvars.example terraform.tfvars  # Edit with your values
terraform init
terraform apply

Documentation

  • Developer Guide — architecture, API reference, data model, services, infrastructure
  • Feature Map — complete catalog of all implemented features and endpoints
  • Authentication — auth system details (passkeys, OAuth, magic links, roles)

License

This project uses card data from the pokemon-tcg-data project.