CardCore
Back to Blog

Building CardCore - March 27, 2026 - Three Pricing Bombs, a Visual Revolution, and Why I'm Looking at Magic

March 27, 20268 min readBy Dan Vohasek
building-in-publicstar-wars-unlimitedbug-fixespricingdeck-buildercollectionrepackconventionmagic-the-gathering

Three pricing bugs that could have cost us everything

Today started with a routine audit and ended with me staring at three critical pricing bugs that have been silently sitting in production. Any one of them could have burned us at the April convention. All three together? That's the kind of thing that kills a platform's credibility before it even gets off the ground.

Bug #1: Bulk pricing wasn't applying at checkout (COREAPP-706). We built this entire bulk pricing system for the convention - $0.15 commons, $0.25 uncommons - and the availability API was completely ignoring it. Customers would see the bulk price on the store page, add to cart, and then get charged market price at checkout. Imagine a player at the booth adding 20 commons expecting to pay $3.00 and the total comes back $14.50. That's not a bug report. That's a scene.

Bug #2: Order items showing the wrong variant (COREAPP-705). A customer buys a Normal copy of a card, the order confirmation says "Foil." The code was pulling variant labels from the cards database (which returns the first variant alphabetically) instead of from the actual order data. So every order item was potentially showing the wrong finish. You buy Normal, the receipt says Foil. You buy Hyperspace, it says Standard. We were deriving the label from the wrong source entirely.

Bug #3: Squeeze detection wasn't enforced at checkout (COREAPP-708). We have this whole effective pricing system where if a card's low price spikes above 1.35x the market price, we detect a "squeeze" and adjust the display price to protect buyers from artificially inflated numbers. That system worked great on the storefront. But at checkout? The validation was using raw market price. A squeezed card showing $8.00 on the page could silently charge $5.00 at the register - or worse, the inverse where someone gets overcharged. The effective price layer wasn't wired into the final price validation step.

All three are fixed. All three have postmortems. And all three were found because I specifically went looking before the convention instead of discovering them when a real customer's money was on the line. The lesson is one I keep relearning: the checkout path needs to be audited separately from the display path. What users see and what they get charged are two completely different code paths, and they can drift apart silently.

A visual overhaul across the entire platform

Once the pricing fires were out, the rest of the day turned into something I've been wanting to do for weeks - a visual refresh across every major feature. Not one thing. Everything.

The deck builder got a full redesign (COREAPP-711). New header bar, reorganized zone rows, a stats panel that actually makes sense, and cost/aspect dot indicators. This came from a design exploration branch on Replit that I've been iterating on, and today it finally merged into main. The deck builder has always been functional but it looked like a spreadsheet. Now it looks like a product someone would actually want to use.

The collection system got the same treatment (COREAPP-702). New tab navigation, a dashboard view, a redesigned set picker, and both grid and card list views. The set picker now groups sets by block and year with completion percentages (COREAPP-707) - so you can see at a glance "I'm 73% complete on Spark of Rebellion" and "I haven't started Secrets of Power." It sounds simple but the block groupings required knowing the actual SWU competitive blocks, not just listing sets chronologically.

Repacks got visual enhancements (COREAPP-714). Merged in a whole branch of visual improvements from the design exploration - better pack opening animations, cleaner card reveals, more polished UI across the board. The repack system is one of our most engaging features and it was starting to look dated compared to the rest of the app. Not anymore.

Order items got color-coded variant badges (COREAPP-703). Foil, Showcase, Hyperspace, Serialized - each variant type now gets its own colored pill badge, and items sort by set rather than randomly. And we shipped a rainbow badge for Prestige Foil cards (COREAPP-709) while fixing a bug where the variant label was saying "Foil Foil." Double Foil. That's how you know you need to look at your label generation logic.

Two sales today

Here's something that gets lost in the technical updates - we made two actual sales today. Real customers, real orders, real money. The platform isn't just a tech project anymore. People are buying cards through CardCore. Every bug fix, every visual polish, every performance improvement - it all compounds into an experience that someone trusted enough to put their credit card into.

Two sales doesn't sound like a lot. But two sales when we haven't launched marketing, haven't done a convention yet, haven't run ads, haven't done anything except exist? That's organic. That's pull, not push. That's proof the product works.

Convention prep is getting real

The table covers came in today - generic ones for now to get the booth looking clean. The custom branded CardCore covers are still on the way. Between the covers, the polos, the Square Terminal, and the convention software we've been building, the booth setup is coming together fast.

But here's the honest part - I had to order more organizers. I pulled some test orders to simulate the convention workflow and it's just harder than I thought. The physical logistics of pulling cards, organizing by order, keeping track of who's waiting for what - there's a reason game stores have systems for this. Bin organizers, labeled dividers, a staging area for pulled orders. The software handles the digital side beautifully. The meatspace side needs more infrastructure than I anticipated. More organizers are on the way.

SWUDB collection import

This one's for the existing SWU community - you can now import your SWUDB collection into CardCore (COREAPP-697). Export a CSV from SWUDB, upload it, and your entire collection carries over. We built a set abbreviation system to map SWUDB's set codes (SOR, SHD, TWI, etc.) to our internal set IDs. Found a couple wrong abbreviations during testing too - what we had as ALT was actually LAW, and SOP was SEC. Fixed those before they could cause import failures.

This matters because the biggest barrier to adoption isn't "is CardCore good enough?" It's "I already have my collection tracked somewhere else." Removing that migration friction is how you grow.

Performance and testing

Shipped CLS and LCP performance fixes across all player-facing mobile pages (COREAPP-695). Moved the min-h-screen class to the layout level so the footer doesn't cause a content layout shift on load. Small change, big Lighthouse score improvement.

And we wrote 46 new Playwright end-to-end tests (COREAPP-698) covering edge cases and error states - empty collections, auth boundaries, mobile-specific flows, malformed URL parameters, error recovery. Our test suite is now at 402 tests across three viewport sizes. The automated tests catch the things I'd miss at 1am.

I'm looking at Magic

Here's the thing I haven't said out loud yet. I've officially started researching Magic: The Gathering.

This has always been the plan. CardCore was always meant to be a multi-game TCG platform - the architecture was built for it from day one. Star Wars Unlimited was the starting point because it's my favorite game and a perfect test case. Newer community, manageable card pool, passionate players who are underserved by existing tools. If CardCore could nail SWU, it could scale to anything.

Magic is the biggest TCG in the world. Decades of sets, tens of thousands of cards, a player base that dwarfs every other game combined. I've started pulling threads - what does the card data look like, what are the format rules, what would the pricing integration need, how different is the collection model. Research. Due diligence. Seeing if the architecture we proved out on SWU can actually deliver on the multi-game promise.

If it can, CardCore stops being a Star Wars Unlimited platform and becomes a TCG platform. That's a different company. That's a different scale. It's exciting and terrifying in equal measure.

What's next

Convention prep is accelerating. Table covers in hand. Custom branded ones on the way. Organizers incoming. The pricing bugs are squashed. The visual overhaul makes every screen feel new.

The first real test is April 12th at TCF Gaming Arena in McDonough - that's the Premier Qualifier for A Lawless Time. That's our dress rehearsal. Real players, real transactions, real booth operations. Everything we've been building gets stress-tested with live humans in 16 days.

Then six days later, April 18th in Atlanta for the Sector Qualifier. The big one. Five tables, 500 players, and a platform that has never looked or worked better than it does right now.

Tomorrow I'm focused on the event management tools - the staff events page got an editing UI today (COREAPP-710) and events now sort by date ascending so the next upcoming event is always on top (COREAPP-713). These are the tools that will run the booth. They need to be bulletproof.


20 Plane tickets. 45 commits. 3 critical pricing bugs fixed. 2 real sales. 1 table cover delivered. And for the first time - Magic research on the whiteboard.