v1.3.0 — Multi-TCG Decks, Card DB, Trade Analyzer, Price Alerts, and Bug Fixes
Summary
v1.3.0 is a major release adding Yu-Gi-Oh! TCG support, a card database preloader, trade analyzer, Collectr import, price alerts, meta decks for all 6 TCGs, and 20+ critical/medium bug fixes including trade persistence data loss, non-Pokemon price refresh, Lorcana/Riftbound meta deck resolution, and navigation hangs.
New Features
Yu-Gi-Oh! TCG Support
- Full set browsing with YGOPRODeck integration
- Card search with TCGPlayer market prices
- Yu-Gi-Oh! meta decks (ygoprodeck.com top decks)
- Preloader support for offline caching
Card Database (Client-Side IndexedDB)
- On first visit, select which TCGs to track
- Preloads all card data into IndexedDB in the background — zero API calls on subsequent searches
- Floating progress pill shows per-game status, ETA, and overall completion
- Interrupted preloads resume silently on refresh
- Search works immediately — uncached TCGs fall back to live APIs
- Two-phase preloader: sets first (~2s), then cards progressively per TCG
- Storage usage display showing combined IndexedDB + localStorage
Trade Analyzer
- Side-by-side trade comparison with cards added via search or camera scan
- Live price delta with winning/losing/even label
- Grading multiplier applied per card (PSA 10 = 2x, etc.)
- Persistent trade state across sessions (separate IndexedDB key)
- Camera scan integration via Tesseract.js OCR
Collectr Import
- Import CSV or Excel exports from the Collectr app
- Maps game names, variants, grading, and sealed products
- Full-screen import overlay with progress bar and phase indicators
- Resolves all 6 TCGs with images + prices automatically
Multi-TCG Meta Decks
- Auto-fetches current tournament meta from each TCG's competitive scene
- Pokémon — Limitless TCG
- Magic — mtgtop8.com
- Lorcana — inkdecks.com
- One Piece — optcg.one
- Riftbound — RiftDecks.com
- Yu-Gi-Oh! — ygoprodeck.com
- Top 10 competitive decks per TCG ranked by meta share
- Cards resolved server-side with exact set code + number matching
- Cached for 24h with version-based invalidation
Price Alerts
- Set "notify when price goes above/below $X" on any card
- Alerts fire via the browser Notification API when prices cross thresholds
- Auto-checked on every dashboard page load
- Manage active and triggered alerts from Settings
Other
- Entire set add to portfolio from any Browse Sets view
- Sealed product search with keyword filtering (boosters, ETBs, tins)
- Graded card multipliers (PSA/BGS/CGC/SGC)
- Reset Everything clears full card cache
- Storage usage in Settings via
navigator.storage.estimate() - 404 catch-all page for invalid routes
Critical Bug Fixes
Trade Store Persistence Conflict
Trade store and portfolio store both wrote to the same IDB key (app_state) with independent debounced saves — one could overwrite the other's unsaved changes. Fixed by adding loadTradeState()/saveTradeState() with a dedicated trade_state key.
Price Alerts Never Auto-Checked
checkAlerts() and notifyTriggered() existed but were never called anywhere. Now invoked after every dashboard price refresh.
Dashboard Non-Pokemon Price Refresh Broken
Dashboard refresh loop used Pokemon-only APIs for all cards. Non-Pokemon cards (MTG, Lorcana, One Piece, Riftbound, Yu-Gi-Oh) failed silently. Fixed by splitting into Pokemon (pokemontcg.io/tcgdex) and non-Pokemon (PriceCharting) refresh paths.
resolveImportedItems Silently Fails for 4 TCGs
After Collectr import, card resolution only worked for Pokemon EN/JP and MTG. Other TCGs were skipped with a comment. Fixed by adding multiSearch resolution for all games.
Medium Bug Fixes
Navigation Hangs
Route transition with mode='out-in' could hang indefinitely when transitionend was delayed (e.g., during IndexedDB writes). Fixed by adding :duration=500 timeout.
Navigation Blank Screen
Vue Router reused component instances across route transitions, causing stale state. Fixed by adding :key on route transitions to force fresh component instances.
Lorcana Meta Deck Cards Not Loading (x2)
- Wrong set field paths: Lorcast API returns set info under a nested
setobject (c.set.name,c.set.code) but code read non-existent top-levelc.set_name/c.set_code. - Missing version-aware matching:
searchLorcanaBySetcompared fallback names like "Elsa — Snow Queen" againstc.name("Elsa") without appending the API'sversionfield. - Incorrect fallback data: All 10 Lorcana meta deck fallback entries had wrong set codes and collector numbers. Corrected against live API data.
Riftbound Meta Deck Cards Not Loading
Empty setCode caused startsWith('') to match all sets, returning wrong cards. Fixed by guarding against empty setCode. Fallback decks replaced with real card names using correct API set codes (OGN, SFD).
Riftbound Card Import Timeout
Parallelized getRiftboundCards and skipped PriceCharting on bulk load to avoid timeouts.
Sealed Search Yielding Card Results
PriceCharting results included single cards. Added isSealed() keyword filter and single-card pattern detection (set codes, collector ratios).
beforeunload Handler Multiplication
Every init() call registered a new beforeunload listener. Fixed with a beforeunloadRegistered flag.
Lorcana Preloader Price Path Mismatch
Used c.tcgplayer.prices.holofoil.market but Lorcast returns c.prices.usd. Added fallback to c.prices?.usd.
One Piece API Response Shape Inconsistency
getOptCards() only checked Array.isArray(d) but API may return {data: [...]} or {cards: [...]}. Added fallback checks.
isCacheFresh First-Card-Only Check
Only checked cachedAt of the first card. Partial caches from interrupted preloads reported as fresh. Added card count check.
Router Missing 404 Catch-All, MockDashboard Route
Invalid URLs rendered blank page. Added /:pathMatch(.*)* catch-all with NotFoundView. Removed /mockup production route.
MTG Paginated Search Replaced with Bulk Data
~545 sequential Scryfall requests (45 min) reduced to 2 requests (~5s) using oracle_cards bulk data.
Sealed Search Filtering Out Prismatic Evolutions
isSealed() didn't check consoleName for keywords. Fixed by checking both productName AND consoleName.
Collectr Import Fixes
- Rewrote to import directly into Pinia store instead of localStorage+reload
- Added BOM stripping for CSV
- Added Excel (.xlsx) support
- Fixed portfolio name mapping (Portfolio Name column, not Category)
- Fixed market price mapping (date-stamped columns)
- Fixed reactivity (black screen after import)
Code Quality & Optimizations
- Hoisted dynamic import:
import('../services/tcg/multiSearch.js')moved outside the loop inresolveImportedItemsper PR review - Empty catch blocks: Replaced with
console.warnin critical price paths - Added SEO meta descriptions to every route
- Navigation logging: Added
router.beforeEachandrouter.afterEachfor diagnostics - Global error handlers:
config.errorHandlerandonErrorCapturedfor silent failure detection - Debounced chart rebuilds (300ms), 404s cached as misses
- API calls batched — max 3-5 concurrent requests
- Retry with backoff on transient errors (429, 5xx, timeout)
- Abort-on-unmount for in-flight API calls
- Decoupled preloader from search — only activate cache after all games finish