Magic the Gathering Card Fetcher

Published
Contents
  1. How it works (big picture)
  2. Writing posts
  3. The MDX transform (in plain English)
  4. The preview component
  5. Being nice to Scryfall

I wanted to drop Magic: The Gathering card previews straight into my posts without stopping to write HTML for each individual card. My “authoring syntax” is simple:

How it works (big picture)

That’s basically it — type a card name in brackets, get a card.

Writing posts

In MDX I just write:

Red decks be like: [[Lightning Bolt]].
Specific print, friendlier label: [[Mox Sapphire (Alpha)|Mox Sapphire]]

The MDX transform (in plain English)

A small remark plugin looks for [[...]] in my content.

If it finds [[label|value]], it creates <MagicCardPreview cardName="value">label</MagicCardPreview>.

If it finds [[text]], it uses the same text for both label and lookup.

I also made it ignore code blocks and links, so it won’t touch things inside backticks.

The preview component

<MagicCardPreview> receives cardName, calls Scryfall’s “fuzzy named” search, and uses the first image it finds (works for single-faced and double-faced cards). In pseudocode:

const url = `https://api.scryfall.com/cards/named?fuzzy=${encodeURIComponent(cardName)}`;
const data = await fetch(url).then(r => r.json());
const src = data.image_uris?.png ?? data.card_faces?.[0]?.image_uris?.png;
// render using that image URL

Being nice to Scryfall

Hot reloads and pages with many previews can fire off a lot of requests. I added a tiny “traffic cop” that paces calls so I stay under 10 requests per second. If Scryfall ever replies “slow down” (HTTP 429), I pause briefly and try again. You don’t see this in the UI; it just keeps dev smooth and friendly to their servers.