Single-user sports card collection manager for tracking owned inventory, organizing nested collections (including set-backed folders), importing manufacturer checklists, measuring set progress, and optionally enriching catalog/pricing data via CardSight.
CardVault is a local-first personal tool. It is not a marketplace, multi-user SaaS, or cloud sync product.
Collectors often track cards in spreadsheets that cannot model checklist progress, parallels/variants, or set organization. CardVault provides a structured inventory with hierarchical folders, set-backed collections, checklist import, variant-aware progress, CSV export, and optional external catalog lookup—with usage budgets so provider calls stay controlled.
| Area | Status |
|---|---|
| Card inventory (quantity, condition, grading, storage, favorite / trade / sale / wishlist) | Implemented |
| Nested collections / sub-collections | Implemented |
| Set-backed collections (from tracked set or manual set) | Implemented |
| Local catalog CSV import (validate → confirm) | Implemented |
| Inventory CSV export | Implemented |
| Inventory CSV import | Not implemented |
| Catalog search (local / mock / optional CardSight) | Implemented |
| Combined checklist XLSX + master-list import wizard | Implemented |
| Checklist progress + group-scoped variants | Implemented |
| Valuation with manual override (provider refresh does not silently overwrite manuals) | Implemented |
| Integration run history + reconciliation counts | Implemented |
| CardSight usage budget, caching, and status UI | Implemented |
| Responsive UI (desktop + mobile nav) | Implemented |
| Multi-user auth / hosted cloud sync | Not implemented |
React + TypeScript (Vite) → FastAPI → SQLAlchemy → SQLite
↘ optional CardSight (server-side only)
- Frontend: React 19, React Router, Vite, Vitest, Oxlint
- Backend: FastAPI, Pydantic Settings, SQLAlchemy 2, Alembic, pytest
- Database: SQLite by default (configurable via
DATABASE_URL) - Providers: Local catalog, mock catalog/pricing, optional CardSight catalog + pricing with cache TTLs and a monthly call budget
Secrets such as CARDSIGHT_API_KEY are read only on the backend. They are never sent to the browser.
cardvault/
README.md # This file
package.json # Root scripts: dev / test / build / lint
backend/
app/ # FastAPI application, services, integrations, models
alembic/ # Schema migrations (source-controlled)
data/catalog_examples/ # Safe synthetic/sample catalog CSV
tests/ # Isolated pytest suite (in-memory DB, no live HTTP)
.env.example # Public env template (no secrets)
frontend/
src/ # React app (pages, components, API clients)
.env.example
Personal databases, .env files, uploads, checklist uploads, and recognition caches are intentionally excluded from publication via .gitignore.
- Full-stack collection manager with nested and set-backed collections, checklist progress, and group-scoped variants.
- Combined XLSX checklist + master-list import pipeline with deterministic parsing, validation, review workflow, and optional AI assist (off by default).
- Provider abstraction for catalog/pricing with local/mock fallbacks, response caching, and monthly CardSight budget enforcement.
- Automated test suites designed to run without personal data or live external APIs (255 backend + 84 frontend tests as of the last local verification).
Do not commit:
- Real
.envfiles or API keys - Personal SQLite databases (
*.db) - Card images under
backend/data/uploads/ - Uploaded checklists under
backend/data/checklist_uploads/ - Local recognition learning files (
backend/data/recognition_patterns.json) - Personal CSV exports or proprietary checklists
Use the provided .env.example templates only. If a provider key was ever committed or shared, rotate it with the provider.
Point DATABASE_URL at a new SQLite file (the example uses cardvault.dev.db). Do not copy or publish a personal cardvault.db.
# backend/.env
DATABASE_URL=sqlite:///./cardvault.dev.db
CATALOG_PROVIDER=local
PRICING_PROVIDER=mock
CARDSIGHT_API_KEY=Verified by provider selection code: with CATALOG_PROVIDER=local (or mock) and PRICING_PROVIDER=mock, and an empty CARDSIGHT_API_KEY, the app starts and supports inventory, collections, local catalog import, and checklist workflows without external API calls.
CardSight remains optional. When configured, CATALOG_PROVIDER=auto prefers CardSight then falls back to local/mock; pricing can use cardsight or mock.
Prerequisites: Node.js 20+, Python 3.9+, and a backend virtualenv at backend/.venv.
# Dependencies
npm install
npm --prefix frontend install
# Backend env (safe defaults — no CardSight)
cp backend/.env.example backend/.env
# Edit DATABASE_URL to a fresh file if needed
# Frontend env (optional)
cp frontend/.env.example frontend/.env
# Create/upgrade the database selected by DATABASE_URL
# WARNING: alembic upgrade mutates the configured database schema.
cd backend
.venv/bin/python -m alembic upgrade head
cd ..
# Run API + UI together
npm run dev- Backend: http://127.0.0.1:8000 (OpenAPI docs at
/docs) - Frontend: usually http://127.0.0.1:5173
Import the labeled development sample (not a complete official checklist):
backend/data/catalog_examples/2025-26_topps_nba_hoops_sample.csv
Via UI: Catalog → Import Checklist → validate → confirm.
From the repository root:
| Command | Purpose |
|---|---|
npm run dev |
Start backend + frontend |
npm test |
Backend pytest + frontend vitest |
npm run test:backend |
Backend tests only |
npm run test:frontend |
Frontend tests only |
npm run build |
Frontend production build (tsc + Vite) |
npm run lint |
Frontend Oxlint |
Backend-only:
cd backend
.venv/bin/python -m pytest
.venv/bin/python -m alembic upgrade head # mutates DATABASE_URL targetalembic upgrade head applies schema changes to whatever database DATABASE_URL points at. Always use a disposable/dev database for experiments. Never run exploratory migrations against a personal collection database you cannot restore.
Backend tests use an in-memory SQLite database, override FastAPI get_db, blank CARDSIGHT_API_KEY, and block live httpx clients. Frontend tests run in jsdom with mocked API modules. They do not read your personal cardvault.db or call CardSight when run as documented.
- Single-user / local SQLite only (no accounts or multi-device sync)
- Inventory CSV export exists; inventory CSV import does not
- No hosted public demo in this repository
- Combined import quality depends on checklist/master-list inputs
- Optional AI master-list interpretation requires separate provider configuration and is off by default
No license file is included in this tree yet. Add a LICENSE before public release if you intend to open-source the code.