Analyze the return on investment of Magic: The Gathering Commander preconstructed decks by comparing current card market values against original MSRP. Built for collectors and resellers who want data-driven purchase decisions.
- 98 Precon Decks - Complete coverage of Commander precons from 2022-2026
- Deck Comparison Table - Side-by-side comparison with sortable columns and filters
- Distributor ROI Calculations - Calculate ROI at wholesale pricing (40% discount default)
- BUY/HOLD/PASS Verdicts - Clear recommendations based on configurable ROI thresholds
- Card Search - Find specific cards across all decks
- Bulk Import - Import decklists from external sources
- Custom Deck Creation - Build and analyze your own deck configurations
- Deck Detail Pages - Individual deck breakdowns with card-by-card pricing
- Live Price Fallback - Automatic Scryfall API queries when static data is unavailable
- Bun runtime
git clone <repository-url>
cd mtg-commander-roi
bun installbun devOpen http://localhost:3000 in your browser.
- Home Page - Select a deck from the dropdown to see instant ROI analysis with market value vs MSRP
- Comparison Page - Browse all precons in a sortable table, filter by year/set, adjust distributor discount
- Deck Detail Pages - Click any deck for card-by-card pricing breakdown and top value cards
- Deck comparison table with sortable columns
- Distributor ROI calculations (40% discount default)
- BUY/HOLD/PASS verdict system
- ROI threshold filters
- Missing price handling (N/A display)
- Live Scryfall fallback when static data unavailable
- TypeScript migration - Full conversion to .tsx with strict mode
- Comparison page enhancements - Year/set filters, sortable columns, batch refresh
- Loading state polish - Progress tracking, skeleton states
- Mobile responsiveness - Responsive layouts across all pages
- Security hardening - Rate limiting, CSP headers, clickjacking protection
- Production tooling - ESLint, pre-commit hooks, Vercel Analytics
- Image optimization - Next.js Image component for Scryfall images
- Historical ROI trends (requires database)
- TCGplayer/CardMarket purchase links
- Play Booster EV analysis
/- Main ROI analyzer/compare- Deck comparison table/deck/[id]- Individual deck details/about- About page/contact- Contact form/privacy- Privacy policy/terms- Terms of service/blog- Blog index/blog/[slug]- Blog posts
- Next.js 15 (App Router)
- React 19
- Tailwind CSS 4
- Bun
Local CLI utilities for data management. Run with bun scripts/<script-name>.ts.
update-prices.ts - Fetches bulk card data from Scryfall and generates static pricing for all decks.
bun scripts/update-prices.ts- Downloads Scryfall bulk data (~85K cards)
- Matches cards to deck set codes for accurate pricing
- Selects cheapest non-promo versions
- Outputs to
public/data/prices.json - Runs automatically via GitHub Actions (3x daily)
fetch-lowest-listings.ts - Scrapes TCGplayer for lowest listing prices on high-value cards.
# First-time setup
bun add playwright
bunx playwright install chromium
# Run scraper
bun scripts/fetch-lowest-listings.ts
# Options
bun scripts/fetch-lowest-listings.ts --limit 20 # Limit cards
bun scripts/fetch-lowest-listings.ts --skip-existing # Skip already scraped
bun scripts/fetch-lowest-listings.ts --visible # Show browser
bun scripts/fetch-lowest-listings.ts --min-price 20 # Set minimum price threshold
bun scripts/fetch-lowest-listings.ts --watchlist-only # Only scrape watchlist cards
bun scripts/fetch-lowest-listings.ts --batch-pause 60 # Pause 60s every 50 cards- Targets cards above minimum price (default $5) in positive-ROI decks
- Use
--batch-pausefor long runs to avoid rate limiting (pauses every 50 cards) - Watchlist file (
public/data/watchlist.json) prioritizes specific cards regardless of price - Rate limited (1.5s between requests) to avoid blocks
- Outputs to
public/data/lowest-listings.json - Manual runs only (not automated)
import-decklist.ts - Imports deck lists from EDHREC precon pages.
bun scripts/import-decklist.ts- Reads deck URLs from
lib/precons.ts(edhrec field) - Parses card lists and commander info
- Outputs to
public/data/decklists.json
fetch-trending.ts - Fetches trending commander cards from EDHREC.
bun scripts/fetch-trending.ts- Scrapes daily/weekly trending commanders
- Outputs to
public/data/trending.json
update-commander-flags.ts - Marks first card in each deck as commander.
bun scripts/update-commander-flags.tspatch-prices-commanders.ts - Syncs commander flags from decklists to prices.json.
bun scripts/patch-prices-commanders.tsCard data and prices provided by Scryfall. Prices update daily via GitHub Actions. All prices shown are for Near Mint (NM) condition.