MTG Stash
Magic: The Gathering collection manager
Next.jsReactFirestoreCloud FunctionsScryfall API
- Status
- In use
- Stack
- Next.js, TypeScript, Firebase (Firestore + Functions), Scryfall API
- Code
- github.com/fudgemasterultra/mtgstash
Problem
A Magic collection grows into boxes, binders, and a few built decks, and at some point you stop being able to answer basic questions about it. What is this actually worth? Do I already own three of these? Is the trade I’m about to make fair?
Scanning apps like ManaBox will get the collection into a CSV, and that is where they stop. A spreadsheet is a snapshot of one afternoon — card prices move daily, so the export is stale the moment it is written. It also has no idea that two people are currently asking you for the same copy of the same card.
Solution
MTG Stash takes the ManaBox export and keeps it alive. Every row is matched against Scryfall so a card resolves to a specific printing rather than just a name, and from there the collection stays priced, charted, and tradeable.
- CSV import that reconciles each row against real Scryfall printings, with autocomplete for adding cards by hand
- Daily price snapshots per card, capped at roughly a year of history — enough to chart the collection’s value over time, cheap enough to read back on every page load
- Trade offers that stay pending until accepted, with conflict detection that flags when two open offers are both counting on the same physical copy
- A public binder view for showing people what’s available, separate from the admin side where things get changed
Worth noting
Nothing is reserved when an offer is made, so total demand across pending offers can quietly exceed what is actually on the shelf. Surfacing that the moment it happens beats discovering it when the second person hits accept. The conflict check is deliberately kept free of Firestore imports so it stays a pure function and can be tested directly.