Skip to content

Add URL-based deck import from popular deck sites#10247

Open
RafaelHGOliveira wants to merge 10 commits intoCard-Forge:masterfrom
RafaelHGOliveira:pr/deck-url-import
Open

Add URL-based deck import from popular deck sites#10247
RafaelHGOliveira wants to merge 10 commits intoCard-Forge:masterfrom
RafaelHGOliveira:pr/deck-url-import

Conversation

@RafaelHGOliveira
Copy link
Copy Markdown

@RafaelHGOliveira RafaelHGOliveira commented Apr 2, 2026

Summary

Adds the ability to import decks directly from a URL in the deck editor. Supported sites:

  • Archidekt (archidekt.com)
  • EDHREC (edhrec.com)
  • Moxfield (moxfield.com)
  • TappedOut (tappedout.net)

Motivation

I started using Forge to play Commander with friends online, and one of the biggest friction points was getting our decks into the game. We all build decks on different websites, so having to manually export and convert was tedious. This feature lets you just paste a URL and go.

What it does

  • New DeckUrlFetcher class that detects the site from the URL and fetches/parses the deck via each site's API or page scraping
  • Correctly handles Commander/partner commanders
  • Extracts deck name from the source site
  • Deduplicates commanders that appear in both commander section and mainboard
  • Filters out maybeboard cards
  • Integrates with the existing DeckRecognizer pipeline — fetched text is passed straight through

Commits

All commits by Rafael Oliveira.

Test plan

  • Import a Commander deck from Archidekt (including partner commanders)
  • Import a deck from EDHREC
  • Import from Moxfield
  • Import from TappedOut
  • Verify deck name is extracted correctly
  • Verify commanders are not duplicated in mainboard
  • Verify maybeboard cards are excluded

Rafael Oliveira added 7 commits April 2, 2026 11:57
Add support for importing decks directly from URLs in the deck import
dialog. Supported sites: Moxfield, Archidekt, EDHREC, TappedOut, and
MTGGoldfish. Each site has a dedicated fetcher that converts the
response to a text format compatible with DeckRecognizer.

The URL field is added to the top of the existing import dialog with
async fetching via SwingWorker to keep the UI responsive.
EDHREC: Rewrite parser to correctly extract card names from nested
cardlists/cardviews JSON structure. Previously only found the commander.

Moxfield: Add unicode unescape for card names with apostrophes
(e.g. Herald\u0027s Horn -> Herald's Horn).

Archidekt: Improve error message when API returns error for newer
deck IDs that aren't supported by the legacy API endpoint.
The extractStringValue method had a 500-char search limit that was
too small for Archidekt's JSON where the "name" field is ~758 chars
after "oracleCard" due to many intermediate fields (legalities, faces,
etc). Increased limit to 2000 chars.
- Extract deck name from API responses (Moxfield, Archidekt, EDHREC, TappedOut) and include as Name: line in imported text
- Remove unnecessary trailing " |" from commander card lines in multi-commander decks
- Commanders now listed on separate lines without pipe separator
Moxfield and EDHREC APIs return commanders in both the commander section
and the mainboard, causing Commander decks to import with extra cards
(e.g. 104 instead of 100 with partner commanders).

Deduplicate by collecting commander/companion names before parsing
mainboard and skipping any card already placed in the command zone.
@Hanmac
Copy link
Copy Markdown
Contributor

Hanmac commented Apr 2, 2026

I think it would be better if we have different sites as different classes

that would be more clean

@tool4ever
Copy link
Copy Markdown
Contributor

tool4ever commented Apr 2, 2026

your class isn't even connected to anything...? :/

imo it's way too much work to try and keep this updated whenever their api changes, that's why they have Export functions in the first place 🤷‍♂️

@Jetz72
Copy link
Copy Markdown
Contributor

Jetz72 commented Apr 2, 2026

I think some of these approaches are fine, others raise concerns.

  • Moxfield - Their API is versioned, so we probably don't have to worry about sudden breaking changes. However, they state in their FAQ that it's not meant for public use. They say they'll assist with non-commercial community projects, which I suspect we qualify as. But I think someone should reach out to them and get permission before doing this.
  • Archidekt - Their API makes no guarantees and offers no support, but as of 6 years ago they supposedly don't mind accessing it as long as you aren't hammering them. Their categories are named arbitrarily by the user, and can contain cards not actually in the deck. We may see structural changes to the API periodically, but it may not present an issue unless they do a big overhaul or Wizards adds a new weird feature like companions.
  • EDHREC - They don't offer any API documentation or comment on third party use. Scraping the HTML is definitely not a stable solution. Looks like you can request a JSON object for a page edhrec.com/foo/bar via json.edhrec.com/pages/foo/bar.json. That response looks totally tailored to their site's own use though. I don't know how they'd feel about us using it. Could try reaching out to them?
  • TappedOut - No public API, but their export tools being accessible via easily copyable URL seems like a green light to access those. Since it's a simple text export, it seems unlikely to see much in the way of breaking changes. Biggest problem in my examination though is the /?fmt=txt method you're using doesn't seem to include any of the deck sections, at least on the decks I tried. Might need more testing?
  • MTGGoldfish - Basically ditto with TappedOut, even down to not seeing categories on text exports. Makes me wonder if there's some broken shared library or back end?

@RafaelHGOliveira
Copy link
Copy Markdown
Author

Thanks for the feedback everyone!

@Hanmac — Good point. I'll refactor into separate fetcher classes per site.

@tool4ever — The integration commit was missing from the PR, my bad. Regarding maintenance: the goal is to reduce friction for multiplayer — copy-pasting export text still requires multiple steps. But I understand the concern about API stability.

@Jetz72 — Really appreciate the thorough analysis.

  • Moxfield: You're right, I'll reach out to them for permission. Worth noting their API is already blocked by Cloudflare (403) in my testing, so this one may need to be dropped or deferred.
  • Archidekt: Agreed it's the most viable. I'll keep it.
  • EDHREC: I can switch to the json.edhrec.com endpoint you mentioned — that's cleaner than HTML scraping. I'll also try reaching out.
  • TappedOut: I'll investigate the missing sections on /?fmt=txt. If it's unreliable I can drop it.
  • MTGGoldfish: Good suggestion, I'll look into adding support.

I'll update the PR with the refactored classes and address the API concerns. Thanks!

Rafael Oliveira added 3 commits April 2, 2026 14:41
Split the monolithic DeckUrlFetcher into individual fetcher classes
for each supported site (Moxfield, Archidekt, EDHREC, TappedOut,
MTGGoldfish). DeckUrlFetcher now acts as a thin dispatcher and
DeckSiteFetcher provides shared HTTP/JSON utilities as a base class.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants