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)
| Path | What'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]/cart | Cart review + checkout |
/[slug]/wants | Want board — buyers can submit "looking for X" |
/[slug]/sell | Sell-to-shop — buyers offer cards to the operator |
/[slug]/wishlist | Buyer's saved cards (localStorage-backed) |
/[slug]/about · /contact · /policies · /shipping · /returns | Static info pages |
Operator dashboard
| Path | What's there |
|---|---|
/dashboard/[slug]/inventory | StorefrontCard list — publish/hide cards, set custom prices, mark featured |
/dashboard/[slug]/orders | Order list — print labels, refund, track |
/dashboard/[slug]/wants | Want submissions inbox |
/dashboard/[slug]/buying | Sell-offer inbox |
/dashboard/[slug]/theme | Theme Studio — full visual + voice customization |
/dashboard/[slug]/settings | General settings — bio, banner, ship-from, Stripe connect status |
The data model
| Table | Purpose |
|---|---|
Storefront | One row per vendor shop. Holds: slug, storeName, accentColor, theme fields (themePreset, displayFont, cardDensity, etc.), Stripe Connect IDs, ship-from address, social links. |
StorefrontCard | A card published to a shop. References slabtrackCardId; caches cardSnapshot JSON for fast rendering. Has customPrice, featured, status (active/hidden/sold). |
Order | Buyer purchase. Stripe payment intent, ship address, tracking, status (pending/paid/cancelled/shipped). |
Want | Buyer "I'm looking for X" submission. Operator responds with matched cards or counter-offers. |
SellOffer | Buyer "I'd like to sell you my X" submission with photos + asking price. Operator can counter, accept, or decline. |
Inquiry | Generic 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.
- Operator visits
/dashboard/[slug]/settings→ "Connect Stripe Account" POST /api/stripe/connect/onboardcreates an Express account + onboarding link- Operator completes Stripe's hosted onboarding (bank info, identity, etc.)
- Stripe redirects to
/api/stripe/connect/return account.updatedwebhook fires → flipsstripeChargesEnabled + stripeDetailsSubmittedon the Storefront row- 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:
- 9 theme presets (Minimal, Standard, Cinematic, Classic, Terminal, Auction, Vault, Neon, Editorial)
- 12 curated color palettes (Royal Purple, Vault Gold, Cyber Neon, etc.)
- Per-shop logo + banner image URLs
- Voice copy: tagline, primary CTA label, featured-section label, announcement bar, about blurb
- Section visibility toggles: live ticker, featured carousel, cross-channel strips, ecosystem sims, USA map
- Live preview iframe of the public storefront, reloads on save
- "Apply SlabTrack Showcase" one-click brand stamp
The buyer purchase flow
- Buyer adds cards to cart (zustand-persisted, per-shop)
- Hits
/[slug]/cart→ reviews → checkout POST /api/stripe/checkout— acquires sale-locks, creates pending Order rows, creates Stripe Checkout Session (idempotency-keyed by lockRef + orderIds)- Buyer pays on Stripe-hosted page
checkout.session.completedwebhook → Order flips to paid, StorefrontCard reservations flip to sold, sale-locks complete + bulk-disengage fires to ToT- Operator clicks "Print Label" in dashboard →
POST /api/shippo/buy-label/[orderId]→ USPS label PDF - 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
- Routes:
slabtrack-storefront/src/app/api/ - Theme system:
src/lib/storefront-theme.ts+src/components/StorefrontThemeProvider.tsx - Stripe checkout:
src/app/api/stripe/checkout/route.ts - Shippo:
src/lib/shippo.ts+src/app/api/shippo/buy-label/[orderId]/route.ts - Schema:
prisma/schema.prisma