# MTG Collection Tracker An [Obsidian](https://obsidian.md) plugin to keep track of a **physical Magic: The Gathering collection**, plus your decks and wantlists, with card data and prices from [Scryfall](https://scryfall.com) and a few price sources next to it. Everything is stored in your own files, on your own devices. There is no account and no server run by this plugin. ## What you can do - **Home**, a dashboard: what you own, recently added cards, your most valuable cards, a colour and rarity breakdown, decks that still need cards, backup status, and market movers. - **My Collection**: any number of lists (plus an *Inbox* for cards you have not sorted yet). Each card has a finish, a condition, a language, an optional grading (PSA / BGS / CGC / other) and an optional custom price. - **My Decks**: mainboard, sideboard and maybeboard, a Commander slot, a *Stacks* view that fans the cards of each group, grouping by type or by function (ramp, removal, draw…), and deck statistics (mana curve, colours, card types). - **My Wantlists**: the cards you are looking for, with a *Mark as acquired* action that moves a card into your collection. - **Card details** for every card: its text, a price history chart, the formats it is legal in, prices from several stores, and the other lists and decks that hold a copy. - **Search** that understands what you type (colours, rarities, types, sets, artists, `legal:modern`, `border:showcase`, `oracle:"draw a card"`, `#235`…). The *Add cards* window searches all of Scryfall; each list has the same search over what it holds. - **Copy, move, merge**: move or copy cards between lists, decks and wantlists, merge lists, merge duplicate cards. - **Import and export**: CSV and plain-text decklists (Moxfield, Archidekt, MTGO, Arena), export to CSV or text, or to the clipboard, one ZIP for several lists at once. - **Backups** you can restore, taken automatically into a vault folder, and **sync between devices** (see below). - **Phones and tablets**: the layout adapts to the width of the pane, with a bottom navigation bar on a phone. ## Installation Requires **Obsidian 1.8.7 or later**, on desktop, iPhone/iPad or Android. ### From the community plugins *Settings → Community plugins → Browse*, search for **MTG Collection Tracker**, install, enable. ### By hand Download `main.js`, `manifest.json` and `styles.css` from the latest [release](https://github.com/Louis1190/obsidian-mtg-collection-tracker/releases), put the three files in `/.obsidian/plugins/mtg-collection-tracker/`, then enable the plugin in *Settings → Community plugins*. The files of every release since 1.0.524 carry a GitHub build attestation, which proves they were built from this repository: `gh attestation verify --repo Louis1190/obsidian-mtg-collection-tracker`. ## Getting started 1. Click the **layers** icon in the ribbon, or run the command **Open MTG collection view**. 2. In *My Collection*, create a list and use **+ Add cards**: search, then add. Or import a CSV / decklist from the `…` menu of a list. 3. Open any card to set its finish, condition, language, grading, and to see its prices. CSV import reads a header row; it recognises `Quantity`, `Name`, `Set code`, `Collector number`, `Finish`, `Condition`, `Language`, `Scryfall ID`, the grading columns and `Custom price`, so the plugin's own CSV export can be imported back. Cards that Scryfall cannot resolve are reported, not silently dropped. ## Prices | Where it shows | Source | | --- | --- | | Card value, TCGplayer column | Scryfall's own prices | | Card Kingdom column | Card Kingdom's public pricelist | | Mana Pool column | Mana Pool's public price list on a computer; on a phone or tablet, the daily MTGJSON price for Mana Pool published for this plugin on GitHub Pages (see below) | | Price history, Cardmarket column, day-change arrows | A daily price history built from [MTGJSON](https://mtgjson.com) (Cardmarket, TCGplayer and Card Kingdom prices) and published for this plugin on GitHub Pages ([mtg-price-history](https://github.com/Louis1190/mtg-price-history)); if it cannot be reached, nothing else is asked and the chart stays empty. Reading these files needs a device that can unpack gzip in its browser engine (every current computer and Android; iPhone and iPad from iOS/iPadOS 16.4): on an older one the price history is simply empty | | Market movers (Home) | The biggest rises and falls of the day, the week and the month, computed every day from the same [MTGJSON](https://mtgjson.com) price data (Cardmarket, TCGplayer and Card Kingdom) and published for this plugin on GitHub Pages; if they cannot be reached, nothing else is asked and the block says so | | Showing one currency everywhere | [frankfurter.dev](https://frankfurter.dev) USD/EUR rate | The price saved with each of your cards (it feeds the values you see) comes from Scryfall and refreshes on its own at the interval you choose (*Settings → Price*, every 24 hours by default). The store columns of a card are fetched when you open the card. Prices are indications taken from third parties, not offers to buy or sell, and can be out of date. Card Kingdom and Mana Pool publish their whole catalogue as one file (65 MB and 49 MB once unpacked). A computer reads it whole. On a phone or tablet, Card Kingdom is read as a stream so that it never sits in memory. Mana Pool's server does not allow that kind of reading, and loading the file the usual way ran Obsidian out of memory, so a phone or tablet reads Mana Pool from small daily files instead (one per card, about 1-6 KB). That price is **the lowest across all conditions, a day old**: the column says *Lowest* with the day under it (*Oct 15*). A computer shows Mana Pool's live Near Mint price. A price more than ten times TCGplayer's (and at least $5) is left out of those files, because MTGJSON's Mana Pool prices occasionally contain impossible values; the column then shows a dash. ## Your data - The collection lives in one file, `data.json`, in the plugin's folder, **or** in a vault folder you choose (*Settings → Data storage*). That is how you sync it with Syncthing, iCloud or any other tool you already use for the vault. - **GitHub storage (optional)**: the data can be kept in a folder of a **private** GitHub repository of your own, with a copy on each device so it works offline. You create the repository and a fine-grained access token limited to it (*Contents: Read and write*); the token stays in Obsidian's secret storage on the device and is never written to your data or your backups. Several devices can edit at the same time: changes are merged, and a card is never deleted by a device that has simply not seen it yet. - Display choices (sort order, view mode, the collapsed navigation…) stay on the device and are not synced. - **Backups**: *Settings → Backup* exports a complete JSON snapshot, and can write one automatically into a vault folder (`MTG Backups` by default, the last 7 kept). To restore, *Choose a saved backup* lists the backups of that folder (the same on every device), and *Load backup file* takes a backup from anywhere else. You always see what a backup contains before anything is replaced. - Small caches (set icons, rules text, format legalities, set lists) are stored in the plugin's folder and can be deleted at any time. ## Network use and privacy The plugin talks to the internet to do its job, and **only** to these services. It has no analytics and no telemetry, and it never sends your collection anywhere except to the GitHub repository you configure yourself. | Service | What for | When | | --- | --- | --- | | `api.scryfall.com`, and the images served by `*.scryfall.io` | Card search, card data, prices, format legalities, set and mana symbols, card images | When you search, open or import cards; in the background to keep the prices and legalities of your cards up to date; and, while a card's detail window is open, for the few cards just before and after the one shown (their text, artwork and images, so they appear at once when you move to them) | | `api.cardkingdom.com` | Card Kingdom prices | The first time a card is opened in a session (read as a stream on a phone or tablet, to spare its memory) | | `manapool.com` | Mana Pool prices (its whole price list) | The first time a card is opened in a session, **computers only** | | `louis1190.github.io` | Price history and the Cardmarket price: one small file per card, named after the first three characters of its Scryfall id (1 of 4,096 files, ~10-40 KB, shared by about 27 cards). Nothing about you or your collection is in the request. A tiny file next to them, `site.json`, is read first (about once per session) and says where the price files are: normally right there, but it can name another `https` address if the files ever have to move, and the plugin then asks that address instead. The last address that worked is kept on your device. The same site also serves the market movers of Home: twelve small lists (about 8 KB each; one per period and vendor choice), the same for everyone, and, **on a phone or tablet only**, the Mana Pool price: a second set of small files with the same names (1 of 4,096, about 1-6 KB) | When a card is opened (and, in the background, for the few cards next to it in the detail window), and when Home shows its market trends | | `api.frankfurter.dev` | USD/EUR exchange rate | Once per session, when a price needs converting | | `api.github.com` | Syncing your data with **your own** private repository | **Only if you turn GitHub storage on** | Requests to Scryfall are rate-limited as their guidelines ask (card search and card data go out at most about twice a second; the image servers have no limit), and carry a `User-Agent` that names this plugin. On a device that asks to save data, the pictures of neighbouring cards are not fetched ahead. ### Links that open in your browser A few buttons open a web page in your default browser, **only when you click them**. These are links, not requests: the plugin itself sends nothing to these sites, and nothing is opened in the background. | Where | Opens | | --- | --- | | *Source:* line under the price history (card details) | `mtgjson.com` | | *Source:* footer under the market trends (Home) | `mtgjson.com` | | Cardmarket column of *Store prices* | A search on `www.cardmarket.com` for the card's name (the name is part of the link) | | TCGplayer, Card Kingdom and Mana Pool columns of *Store prices* | The product page link that Scryfall, Card Kingdom and Mana Pool give for that printing (`https://` only); on a phone or tablet, Mana Pool's link is built from the card's set and number (`manapool.com/card//`) | ## Files outside your vault Everything the plugin keeps lives inside your vault: its own folder (`data.json`, caches, safety copies), the data folder you may choose, the backup folder and the export folder. The exceptions are a few per-device preferences and the GitHub token, which Obsidian keeps in its own storage on the device. The plugin reaches outside the vault in these cases only, each one started by an action of yours: - **Opening a file you pick.** *Load backup file* (settings), *Import* (CSV or text decklist) and *Load .svg file* use the system's file chooser; the plugin reads that one file and nothing else, and writes nothing. - **Saving an export on desktop.** Exports (CSV, text, ZIP, backup) go through the browser's *Save as* dialog: you choose where the file goes. - **Saving an export on a phone or tablet.** The export window writes into a vault folder (`MTG Exports` by default), and its **Share…** button hands that file to the system's share sheet or default app. On **Android**, **Device folder…** lets you pick a folder of the device with Obsidian's own folder picker and writes the file there; it never overwrites an existing file. ## Clipboard and device storage - **Clipboard.** The plugin only ever *writes* to it, when you click *Copy to clipboard* (or *Copy list* after an import). It never reads what you copied elsewhere. - **Device storage.** A few per-device preferences (the view mode of each section, the last export folder…) are kept in Obsidian's per-device local storage (its own `saveLocalStorage`, never the browser's directly), never in `data.json`, so they are neither synced nor backed up. If you turn GitHub storage on, its access token goes to Obsidian's secret storage when your version has one, otherwise to the same device storage. ## Building from source ```bash npm ci npm test # unit tests (Vitest) npm run build # type check, then bundle to main.js ``` `styles.css` and `manifest.json` are used as they are. ## Credits and disclaimer - Card data, images and symbols come from [Scryfall](https://scryfall.com). This plugin is not made by or affiliated with Scryfall. - Magic: The Gathering is a trademark of Wizards of the Coast LLC. This plugin is unofficial Fan Content permitted under the [Fan Content Policy](https://company.wizards.com/en/legal/fancontentpolicy). It is not approved or endorsed by Wizards. Portions of the materials used are property of Wizards of the Coast. ©Wizards of the Coast LLC. - The price history is built from [MTGJSON](https://mtgjson.com) (MIT License, © Zach Halpern), which collects the prices of Cardmarket, TCGplayer and Card Kingdom. This plugin is not affiliated with MTGJSON. - Card Kingdom, Mana Pool, TCGplayer, Cardmarket, PSA, BGS and CGC names and logos belong to their owners and are used only to say where a price or a grade comes from. This plugin is not affiliated with any of them. - The small language flags are flat icons from a royalty-free icon set. ## License [MIT](LICENSE) © 2026 Louis