The web app is the most visual way to work with MTG Cheaper Deck. It loads your entire Moxfield deck at once and presents every card with its Scryfall image, up to five cheaper alternatives lined up side-by-side, and a live running total in a fixed bottom bar. Choose it when you want a point-and-click workflow — no typing required after the initial URL — or when you want to see what a replacement card actually looks like before committing to it.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/invvd/mtg-cheaper-deck/llms.txt
Use this file to discover all available pages before exploring further.
Starting the web app
Run the following command from the project root. Flask starts onhttp://127.0.0.1:5000 and your default browser opens automatically after one second.
Workflow
Enter your Moxfield deck URL
On the landing page, paste a public Moxfield deck URL (e.g.
https://moxfield.com/decks/YOUR-DECK-ID) into the input field and click Cargar mazo. The server fetches the deck from Moxfield, matches each card against the local database, and computes suggestions for every card that has a known price.Browse your deck grouped by card type
The
/deck page shows every card in the deck with its Scryfall card image, price, and up to five suggestion buttons to the right. A sidebar on the left lets you filter by card type (Creature, Instant, Sorcery, etc.) so you can focus on one section at a time. The commander is displayed separately at the top with a gold border — no replacements are suggested for it.Click a suggestion to replace a card
Each suggestion is rendered as a clickable card image button showing the candidate’s name, price, percentage savings, and similarity score. Clicking one fires an AJAX request to
POST /replace — the page does not reload. The selected button gains a green border, the plain-text list in the top-right panel updates instantly, and the bottom bar recalculates the totals.Revert to the original card
The original card is also rendered as a button (with a dashed blue border). Clicking Original at any time sends
choice=original to /replace and restores that slot to its starting card. The plain-text list and totals update immediately.Copy the plain-text deck list
The textarea in the top-right panel (and the Copiar button in the bottom bar) always reflects the current state of the deck — originals where no replacement was chosen, and the chosen replacement where one was accepted. Click Copiar lista or Copiar to write the list to the clipboard, ready to paste into MTGO, Moxfield, or any other tool.
Sort options
The Ordenar por dropdown in the sidebar controls the order in which cards appear on the/deck page. The order is fixed at page load based on each card’s best suggestion (the top-ranked one), so it does not change as you accept replacements.
| Key | Label | Description |
|---|---|---|
price | Precio original (mayor a menor) | Most expensive original cards first — the default. |
savings | Mayor ahorro ($) | Cards where the best suggestion saves the most absolute dollars first. |
savings_pct | Mayor ahorro (%) | Cards where the best suggestion saves the highest percentage first. |
similarity | Mayor similitud (puntaje) | Cards whose best suggestion has the highest similarity score first. |
Live price total
The fixed bottom bar shows three figures that update automatically every time a replacement is accepted or reverted — no page reload needed:- Original — the sum of all original card prices (quantity × unit price for each card with a known price).
- Ahorrado — the difference between the original total and the current total.
- Total — the current deck price with all chosen replacements applied.
Plain-text export
The copyable deck list uses the standard Commander format produced byplain_text.build_plain_text(). The layout is:
Commander section header comes first, followed by one quantity name line per commander. A blank line separates it from the Deck section header, which is followed by all remaining cards in the same quantity name format. Cards without a known price or a matched local entry are included in their original positions and are never replaced.
State management
All deck state is held in memory on the local Flask server in a single
STATE dictionary. Refreshing the page or navigating away does not reset your choices — state persists as long as the Python process is running. However, clicking Resetear in the bottom bar clears all chosen replacements and returns every card to its original. Stopping and restarting webapp.py also clears all state. The app is designed for single-user local use only and should not be exposed to the internet or shared across multiple browser sessions.Routes
| Method | Route | Description |
|---|---|---|
GET | / | Landing page with the deck URL input field. If a deck is already loaded, redirects to /deck. |
POST | /load | Accepts the link form field, fetches and processes the deck, then redirects to /deck. Returns to / with an error query parameter on failure. |
GET | /deck | Main deck view. Accepts an optional ?sort= query parameter (price, savings, savings_pct, or similarity). Redirects to / if no deck is loaded. |
POST | /replace | JSON API endpoint. Accepts idx (card index) and choice ("original" or a zero-based integer index into the suggestions list). Returns updated plain_text, row_savings, totals, idx, and chosen. |
POST | /reset | Clears all chosen values for every card entry and redirects back to /deck, preserving the current sort order via the sort form field. |