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
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, Tailwind CSS 4, shadcn/ui, Recharts |
| Backend | ASP.NET Core 10, Entity Framework Core 10, SignalR |
| Auth | ASP.NET Identity, FIDO2 (passkeys), OAuth 2.0, magic links |
| Database | PostgreSQL 15 |
| Pricing | 7 price sources (Scrydex primary), daily CronJob |
| Card Data | pokemon-tcg-data (git submodule, ~15,000+ cards) |
| Postfix (SMTP) | |
| Infrastructure | Kubernetes, Terraform, Traefik, Keel (auto-deploy) |
| CI/CD | GitHub 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
- .NET 10 SDK
- Node.js 22+
- PostgreSQL 15 (or Docker)
- Git (for submodule)
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.