A fast, zero-login web tool for Magic: The Gathering players to paste, visualize, and share decklists. Card data from the Scryfall API.
Live: https://mtg-deck-viewer-production.up.railway.app/
- Paste a decklist in Arena, MTGO, or generic format
- See your cards as stacked images with hover-to-inspect
- Share via URL with compressed encoding (Commander-sized decks fit in a URL)
- View stats -- price total, mana curve, format legality
Supports mainboard, sideboard, Commander, and Companion sections.
4 Lightning Bolt
4 Counterspell
2 Snapcaster Mage
Sideboard
2 Negate
1 Dispel
4x Lightning Bolt (MH3) 123
4x Counterspell (DMR) 47
SB: 2 Negate
SB: 1 Dispel
git clone https://github.com/pcapriolo/mtg-deck-viewer.git
cd mtg-deck-viewer
npm install
npm run dev # http://localhost:3000| Command | Description |
|---|---|
npm run dev |
Start dev server |
npm run build |
Production build (includes type-check) |
npm start |
Start production server |
npm run test:run |
Run all tests once |
npm test |
Run tests in watch mode |
railway up |
Deploy to Railway |
Next.js 14 App Router
├── src/app/page.tsx # Home -- paste + view
├── src/app/d/[encoded]/page.tsx # Shareable deck URLs (SSR + OG tags)
├── src/app/stats/page.tsx # Bot metrics dashboard
├── src/app/status/page.tsx # Agent status dashboard
├── src/app/api/
│ ├── ocr/route.ts # Claude Vision OCR
│ ├── stats/route.ts # Bot metrics API
│ ├── track/route.ts # Interaction tracking
│ └── agent-status/route.ts # Agent heartbeat + backlog API
├── src/components/ # DeckViewer, CardHover, ManaCurve, etc.
├── src/lib/ # Parser, Scryfall client, encoder, types
└── bot/ # Twitter bot (separate service)
├── bot.ts # Polling loop + reply orchestrator
├── ocr.ts # Claude Vision two-pass OCR
├── twitter.ts # X/Twitter API v2 client
└── scryfall.ts # Card lookup
This project runs itself using Claude Code scheduled tasks. Four loops work together to operate, monitor, improve, and plan:
YOU (Telegram + GitHub PRs + /status)
|
v
+------------+ +-------------------+ +-------------+
| PLAN (24h) |---->| feature-backlog |<----| REVIEW (1h) |
| analyze | +--------+----------+ | detect+fix |
| prioritize | | +-------------+
+------------+ v
+----------------+ +-------------+
| IMPROVE (1-4h) | | OPERATE(1h) |
| pick -> build | | Twitter bot |
| test -> PR | +-------------+
+--------+-------+
v
claude-progress.txt <-- all agents read/write
| Loop | What it does | Frequency |
|---|---|---|
| OPERATE | Twitter bot finds decklist tweets, replies with @mtgviewer |
Every 60 min |
| REVIEW | Checks /api/stats for quality issues, uses Claude Vision to diagnose OCR failures, creates fix PRs |
Every 60 min |
| IMPROVE | Picks a task from the backlog, implements on a feature branch, runs tests + QA + code review, creates a PR | Every 1-4 hours |
| PLAN | Analyzes metrics, updates the backlog, checks agent liveness, sends daily digest | Every 24 hours |
- Nothing deploys without your merge -- all work on feature branches
- Tests are the gate -- agents can't commit if tests fail, test count never decreases
- Regression gate -- QA health score must not drop; if it does, branch is reverted, no PR created
- One PR per session -- limits blast radius
- Dead man's switch -- PLAN alerts on Telegram if any agent goes silent
- Tiered notifications -- Critical/Action/Digest/Heartbeat levels prevent noise
| Channel | What you see |
|---|---|
| Telegram | Push alerts for actions + problems, daily digest |
/status |
Live health score, agent heartbeats, backlog, recent activity |
/stats |
Real-time bot metrics, OCR accuracy, latency |
| GitHub PRs | Exact diffs with test counts and QA results |
These files coordinate the agents across sessions (gitignored, local only):
claude-progress.txt-- Cross-session handoff. Current state, recent completions, known issues, health scores.feature-backlog.json-- Prioritized task queue. PLAN writes, IMPROVE pulls, REVIEW adds issues.agent-heartbeat.json-- Timestamps for each agent's last run. PLAN uses this as a dead man's switch.
- Install Claude Code
- Create the state files (see templates in IMPROVE.md and PLAN.md)
- Register scheduled tasks:
# In Claude Code, register these as scheduled tasks: # IMPROVE -- every 60 min, instruction file: IMPROVE.md # PLAN -- every 24 hours, instruction file: PLAN.md # OPERATE -- every 60 min, instruction file: COWORK.md # REVIEW -- every 60 min, instruction file: REVIEW-CRON.md - Set up Telegram bot for notifications (token + chat ID in the .md files)
The harness leverages these Claude Code skills for quality gates:
IMPROVE loop: /browse (visual verify) -> /qa (regression check) -> /review (code review) -> /eval (output quality) -> /ship (create PR)
PLAN loop: /browse (production check) -> /benchmark (performance) -> /retro (weekly) -> /plan-ceo-review (strategy) -> /plan-eng-review (architecture) -> /plan-design-review (UI quality)
ANTHROPIC_API_KEY-- For OCR API route (Claude Vision)NEXT_PUBLIC_BASE_URL-- Production URL (optional, falls back to Railway domain)
X_BEARER_TOKEN,X_APP_KEY,X_APP_SECRET,X_ACCESS_TOKEN,X_ACCESS_SECRET-- Twitter API v2X_BOT_USER_ID-- Bot's numeric user IDANTHROPIC_API_KEY-- Claude Vision for OCRDECK_VIEWER_URL-- Base URL for generated linksPOLL_INTERVAL-- Polling interval in seconds (default: 60)
- Bot token and chat ID are configured in IMPROVE.md, PLAN.md, and REVIEW-CRON.md
npm run test:run # 118 tests across 11 filesTests cover: decklist parsing (all formats), Scryfall utilities, URL encoding round-trips, metrics tracking, bot logic, reply variants, conflict resolution, interaction logging, and notifications.
MIT