Architecture

Three repos, one ecosystem

SlabTrack is a constellation: an operator brain (slabtrack), a marketplace where buyers play games for cards (thisorthat), and a storefront platform where vendors run their own shops (slabtrack-storefront). Each is an independent Next.js app with its own database — they coordinate via webhooks, JWT auth, and a shared sale-lock layer.

The mental model

┌──────────────────────────────────────────────────────────────┐
│                       slabtrack (brain)                       │
│          collection · pricing · strategist · bridge           │
│                    Express + Postgres + React                 │
└──────────────────────────────────────────────────────────────┘
                ▼ webhook ingest         ▲ engage/disengage
                │  (push lots/singles)   │  (canonical state)
┌───────────────┴───────────────┐ ┌──────┴────────────────────┐
│   thisorthat (marketplace)    │ │  storefront (per-vendor)  │
│   Next.js 16 + Postgres       │ │  Next.js 16 + Postgres    │
│   buyer plays Flip / Pull     │ │  buyer direct-buys cards  │
│   Stripe direct charges       │ │  Stripe Connect (Express) │
│   Shippo labels               │ │  Shippo labels            │
└───────────────────────────────┘ └──────────────────────────┘

Repo-by-repo

slabtrack Brain

The operator-side dashboard. Catalogs every card you own, prices them, scores them, and routes them to the right channel via the Strategist. Also runs the Command Bridge — the cross-channel awareness layer that knows which card is live where, and the Sync Center that reconciles SlabTrack's view with each satellite.

thisorthat Marketplace

The buyer-facing game marketplace. Buyers pick cards, then choose a Flip (50/50 spread) or Pull (mystery stack from 2-5 cards) — the outcome decides their final price, but the card always ships. Provably fair via SHA-256 + Solana on-chain seed anchoring.

slabtrack-storefront Multi-tenant

Vendor storefronts. Each operator gets their own slug at storefront.slabtrack.io/[slug] with their own theme, logo, accent color, and Stripe Connect account. Direct-buy commerce (no games) — the buyer adds cards to a cart and checks out via Stripe-hosted Checkout.

Auth — the JWT shared secret

All three repos verify JWTs signed with the same JWT_SECRET. SlabTrack issues the JWT at login; ToT and Storefront accept it via the handoff route (/auth/handoff?token=…) which sets a same-origin cookie on the satellite.

⚠ JWT_SECRET must match

If JWT_SECRET drifts between repos, the operator can sign in to SlabTrack but every handoff to ToT / Storefront fails silently with "auth required." Triple-check the value in Railway env-var settings on all three services.

Order lifecycle (storefront example)

  1. Buyer adds cards to cart → POST /api/stripe/checkout on storefront
  2. Storefront acquires sale-locks for each card across SlabTrack + ToT (so the same card can't be bought twice on different channels)
  3. Storefront creates pending Order rows + Stripe Checkout Session (idempotent)
  4. Buyer pays on Stripe-hosted page
  5. checkout.session.completed webhook fires → flips Orders to paid + reservations to sold + completes the sale-locks (which fan out bulk-disengage to ToT/etc.)
  6. Operator clicks "Print Label" in dashboard → /api/shippo/buy-label/[orderId] purchases USPS label, stores tracking
  7. Buyer email fires with tracking link

Webhook endpoints (production URLs)

FromToEndpointPurpose
StripeStorefrontstorefront.slabtrack.io/api/stripe/webhookOrder paid / refunded / failed
StripeToTthisorthat.slabtrack.io/api/stripe/webhookPull/Flip play settlement, refunds
SlabTrackToTthisorthat.slabtrack.io/api/webhook/ingestEngage/disengage, lot/single publish
SlabTrackStorefrontstorefront.slabtrack.io/api/storefronts/[slug]/cardsCard publish from SlabTrack
ToTSlabTrackwww.slabtrack.io/api/webhooks/ecosystem-transfer/...Sale events, bulk disengage
StorefrontSlabTrackwww.slabtrack.io/api/webhooks/ecosystem-transfer/...Same — sale propagation

Where data lives

Each repo has its own Postgres database (separate Railway services). Cards are referenced across repos by slabtrackId (the canonical SlabTrack cards.id). Listings/orders/etc. are owned by whichever repo creates them and never cross-leak.

DataLives inReferenced via
Card master record (player, set, year, image, comp price)SlabTrackcards.id
ToT Listing (FlipConfig, lot/single, theme metadata)ToTListing.cards[].card.slabtrackId
Storefront listing (custom price, snapshot, featured flag)StorefrontStorefrontCard.slabtrackCardId
Sale state (which channel currently owns the card)SlabTrackcard_channels table
Order (buyer email, payment intent, ship address)Wherever the sale happenedLocal Order table