The Three Apps · App #3

Storefront — multi-tenant card shops

Storefront is the multi-tenant platform where each vendor gets their own slug at storefront.slabtrack.io/[slug] with their own theme, logo, accent color, and Stripe Connect account. Buyers do direct-buy commerce — no games, just add to cart and check out.

Public surfaces (per shop)

PathWhat's there
/[slug]Public storefront — hero + featured carousel + filterable shop grid + sticky cart
/[slug]/cards/[id]Individual card detail page (slide-over preferred from /[slug])
/[slug]/cartCart review + checkout
/[slug]/wantsWant board — buyers can submit "looking for X"
/[slug]/sellSell-to-shop — buyers offer cards to the operator
/[slug]/wishlistBuyer's saved cards (localStorage-backed)
/[slug]/about · /contact · /policies · /shipping · /returnsStatic info pages

Operator dashboard

PathWhat's there
/dashboard/[slug]/inventoryStorefrontCard list — publish/hide cards, set custom prices, mark featured
/dashboard/[slug]/ordersOrder list — print labels, refund, track
/dashboard/[slug]/wantsWant submissions inbox
/dashboard/[slug]/buyingSell-offer inbox
/dashboard/[slug]/themeTheme Studio — full visual + voice customization
/dashboard/[slug]/settingsGeneral settings — bio, banner, ship-from, Stripe connect status

The data model

TablePurpose
StorefrontOne row per vendor shop. Holds: slug, storeName, accentColor, theme fields (themePreset, displayFont, cardDensity, etc.), Stripe Connect IDs, ship-from address, social links.
StorefrontCardA card published to a shop. References slabtrackCardId; caches cardSnapshot JSON for fast rendering. Has customPrice, featured, status (active/hidden/sold).
OrderBuyer purchase. Stripe payment intent, ship address, tracking, status (pending/paid/cancelled/shipped).
WantBuyer "I'm looking for X" submission. Operator responds with matched cards or counter-offers.
SellOfferBuyer "I'd like to sell you my X" submission with photos + asking price. Operator can counter, accept, or decline.
InquiryGeneric contact form submissions.

Stripe Connect Express

Each shop owner onboards their own Stripe account via Stripe Express. Funds settle directly into their account; the platform takes a 3% application fee on each charge.

  1. Operator visits /dashboard/[slug]/settings → "Connect Stripe Account"
  2. POST /api/stripe/connect/onboard creates an Express account + onboarding link
  3. Operator completes Stripe's hosted onboarding (bank info, identity, etc.)
  4. Stripe redirects to /api/stripe/connect/return
  5. account.updated webhook fires → flips stripeChargesEnabled + stripeDetailsSubmitted on the Storefront row
  6. Public storefront's buy buttons activate

Until step 6 completes, the public shop shows a "Setup in progress" state.

Theme Studio (the customization layer)

Each operator can fully customize their shop's identity — see Theme Studio deep dive. Highlights:

The buyer purchase flow

  1. Buyer adds cards to cart (zustand-persisted, per-shop)
  2. Hits /[slug]/cart → reviews → checkout
  3. POST /api/stripe/checkout — acquires sale-locks, creates pending Order rows, creates Stripe Checkout Session (idempotency-keyed by lockRef + orderIds)
  4. Buyer pays on Stripe-hosted page
  5. checkout.session.completed webhook → Order flips to paid, StorefrontCard reservations flip to sold, sale-locks complete + bulk-disengage fires to ToT
  6. Operator clicks "Print Label" in dashboard → POST /api/shippo/buy-label/[orderId] → USPS label PDF
  7. Buyer-shipped email fires with tracking link

Cross-channel coordination

If DUAL_LISTING_ENABLED=true, a card can be on both Storefront AND ToT. Sale-locks coordinate: when checkout starts on either, the card becomes unbuyable on the other for 10 minutes. Full sale-lock flow.

Code references