Eli Bakal

Binder, a collection and deck-building app for Magic: The Gathering

My Magic collection tracker on the App Store, and a running experiment in what a free app with affiliate links actually earns.

Solo designer-engineer · 2025-2026 · Shipped

Swift · SwiftUI · SwiftData · VisionKit · Scryfall API · TCGplayer affiliate · Xcode · Cursor · Claude

I scan a physical Magic: The Gathering card with my phone and Binder identifies it, prices it, and files it into a collection, deck, or wishlist in seconds, and the app has earned $3.79 doing it.

1.7%

of the way to break-even

$3.79 recovered$219 spent

at the current pace, break-even lands around 2081

Binder is free, with no ads and no in-app purchases; the only revenue is a small commission when someone buys a card through a TCGplayer link inside the app. I tested the affiliate model on purpose instead of guessing at it: I took Apple's free Search Ads course and spent their promo credit acquiring real installs at $11.59 each, against the $99-a-year developer account and roughly $120, an estimate rather than an itemized bill, for three months of Cursor and Claude. Well into the red before I even think about pricing my own time. That's fine. Shipping a niche app for free and learning how App Store economics actually work was the point, not turning a profit.

Context

I've played Magic: The Gathering for years and had thousands of physical cards spread across boxes and binders with no real sense of what they were worth or how they'd sort into decks. I started building Binder in April 2025 to answer that one question, and over the months since it grew from a pricing lookup into a full collection and deck-building app: camera scanning, typed containers for collections, decks, and wishlists, a deck builder that checks Commander decks against the official power brackets, a life counter, and price tracking, all running against live Scryfall data. I designed, built, and shipped it alone: data model, scanning, deck logic, pricing, and every screen. It's live on the App Store as MTG Binder, a free 2.7 MB download rated 5.0 across 8 reviews, with a "Data Not Collected" privacy label because there are no accounts and no analytics.

Problem

A collection tracker built for a personal binder and a deck builder built for constructing decks are usually two separate apps, and I wanted one app to do both without either side feeling bolted on. 1Decision 01A user's cards live in more than one context at once: a raw collection, playable decks, and a wishlist of what to buy next. Constraint: All three needed to feel like first-class app structure, not tags stuck onto the same flat list of cards. Chose: I built two SwiftData entities, Card and a polymorphic CardContainer, where a container carries a type (collection, deck, or wishlist), a color tag, and a to-many relationship to cards. Traded: Every container-level feature, like deck formats or wishlist alerts, has to route through that one polymorphic type instead of a purpose-built model, which adds indirection up front. Typing a card's name in by hand doesn't scale past a few dozen entries, and a shoebox of a few thousand needed a way in that didn't mean typing each name by hand. 2Decision 02Cards had to enter the app fast, without hand-typing a name for each one, often in batches of a dozen or more at a time. Chose: I used VisionKit to run OCR on the camera feed, matched the recognized text against the Scryfall API, and built a batch scanner on top so a stack of cards gets logged in one pass instead of one screen per card. Traded: OCR still misreads a name often enough that I kept manual search as a fallback rather than trusting a scan blindly. Once decks were a real container type, a Commander deck needed to be checked against something more useful than a legality flag, because two legal 100-card decks can play nothing alike. 3Decision 03Commander decks range from casual to competitive, and 'legal' says nothing about how a deck actually plays at a table. Chose: I built a Commander Bracket Analyzer, a 386-line scoring service that checks a deck for Game Changers, tutors, extra-turn effects, mass land destruction, and a hardcoded table of roughly 90 known infinite combos, and maps the result to the official 1-5 bracket system. Traded: The combo table is something I maintain by hand rather than a live feed, so it goes stale as new cards print. None of that pays for itself, so the last real decision was whether the app would make any money at all. 4Decision 04A niche hobby app either charges money, shows ads, or finds another way to cover its costs, and each choice changes how people use it. Chose: I kept Binder free with no ads and no in-app purchases, and routed every buy action (card detail, wishlist rows, batch scan, mass export) through a TCGplayer affiliate link that wraps the exact card, printing, and foil finish being viewed. Traded: The upside caps at a small commission on cards people were already going to buy, which is why the break-even meter at the top moves as slowly as it does.

Result

Binder today is a lot more than a price lookup. It scans a card or a stack of them, sorts everything into collections, decks, and wishlists with color tags, and builds decks across every format from Standard to Commander and cEDH, with sideboards and up to two partner commanders. A deck view shows its mana curve and type breakdown, and the bracket analyzer scores it 1 through 5. The Game tab runs a life counter for 1 to 6 players with commander damage and poison counters. Every card carries its Scryfall rulings, cached for 30 minutes, and finish-aware pricing for foil and etched versions, including a rendered foil sheen and finish filters that carry into the TCGplayer links. Prices refresh manually against Scryfall, batched 75 cards per request through a rate-limited client, and each refresh surfaces the top 3 movers over the last 24 hours. Getting cards out is as easy as getting them in: a CSV export, or a TCGplayer Mass Entry export that copies a quantity-and-name list to the clipboard and opens TCGplayer's bulk-add page.

Under the hood it's about 100 Swift files in an MVVM structure with an 11-service layer, still built on the same two SwiftData entities from day one, with roughly 86 unit tests concentrated on the logic that's easiest to get quietly wrong: affiliate link building, container relationships, and price baselines.

Download MTG Binder on the App Store

iCloud sync was the plan after the first release. It hasn't shipped. There's a design doc for a Supabase-based sync layer, but the collection still lives on one device today. The app went through 127 commits between November 2025 and January 2026 alone, on top of earlier work that predates the git history, and it's still just me building it in Cursor and Claude, one feature at a time.

Binder app icon
Binder's app icon.

Gallery

Deck stats for a 96-card Commander build: mana curve, card type breakdown, and the bracket analyzer scoring it Bracket 3, Upgraded
Deck stats for a 96-card Commander build: mana curve, card type breakdown, and the bracket analyzer scoring it Bracket 3, Upgraded
Card detail for The One Ring priced at $472.75, with the Buy on TCGplayer and Add to Wishlist actions
Card detail for The One Ring priced at $472.75, with the Buy on TCGplayer and Add to Wishlist actions
Batch scan mid-capture, OCR guide frames locked onto a card with one scan already queued
Batch scan mid-capture, OCR guide frames locked onto a card with one scan already queued
Collections tab listing Commander decks with card counts and live values
Collections tab listing Commander decks with card counts and live values
My Cards list totaling $3,951.44 across the collection, each card with set, finish, and current price
My Cards list totaling $3,951.44 across the collection, each card with set, finish, and current price
Two-player life counter from the Game tab, mirrored so both players read their own total
Two-player life counter from the Game tab, mirrored so both players read their own total