Architecture
SlabTrack is three Next.js / Express applications that coordinate via webhooks, JWT auth, and a shared sale-lock layer. Each runs independently with its own database — they're loosely coupled by design so any one can degrade without taking the others down.
The three repos
| Repo | Domain | Stack | Owns |
|---|---|---|---|
slabtrack | slabtrack.io | Express 5 + React 19 (Vite) + Postgres | Cards, channels, scanners, strategist, command bridge |
thisorthat | thisorthat.slabtrack.io | Next.js 16 + Postgres + Prisma | Listings, plays, orders |
slabtrack-storefront | storefront.slabtrack.io/[slug] | Next.js 16 + Postgres + Prisma | Storefronts, storefront cards, orders |
Data flow
SlabTrack (operator brain)
│
├─▶ Storefront satellite (publishes cards, receives sale events)
│ ├─ Stripe Connect Express
│ └─ Shippo (per-shop ship-from)
│
└─▶ ToT satellite (publishes listings, receives sale events)
├─ Stripe direct charges
└─ Shippo (one global ship-from)
Cross-cutting: JWT auth (shared secret), Sale-locks (cross-channel
coordination), Reconciler (drift detection)
Authentication — shared JWT
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. All three repos must have the same JWT_SECRET or the SSO handoff silently fails.
Webhook map
| From | To | Endpoint | Triggers |
|---|---|---|---|
| Stripe | Storefront | /api/stripe/webhook | Order paid / failed / refunded |
| Stripe | ToT | /api/stripe/webhook | Pull/Flip settlement, refunds, disputes |
| SlabTrack | ToT | /api/webhook/ingest | Card publish (singles + lots) — auto-publishes Listings |
| SlabTrack | Storefront | /api/storefronts/[slug]/cards | Card publish |
| ToT | SlabTrack | /api/webhooks/ecosystem-transfer/... | Sale events, bulk-disengage propagation |
| Storefront | SlabTrack | /api/webhooks/ecosystem-transfer/... | Same — sale propagation |
Where data lives
| Data | Lives in | Cross-ref via |
|---|---|---|
| Card master record (player, set, year, image, comp) | SlabTrack | cards.id |
| Channel state (where a card is right now) | SlabTrack | card_channels |
| ToT Listing + FlipConfig + Pull state | ToT | References card.slabtrackId |
| Storefront listing (custom price, snapshot) | Storefront | References StorefrontCard.slabtrackCardId |
| Order (buyer email, payment intent, shipping) | Wherever the sale happened | Local Order table on ToT or Storefront |
| Operator users / consignors / pricing intel | SlabTrack | Auth via JWT, data via API |
Each app having its own Postgres means you can take one offline (deploy issue, scaling, migration) without breaking the others. ToT can keep selling while Storefront's down. SlabTrack can't push new cards until ToT comes back, but existing listings keep working.
Sale-lock coordination
Cross-channel sales coordination uses the sale-lock system: when a buyer enters checkout on any channel, that channel locks the card across the ecosystem. Lock TTL = 10 minutes. Released on cancel / failure; flipped to "sold" + bulk-disengage on success.
Deployment
All three deployed on Railway with separate services per repo + a Postgres service per repo. Custom domains routed via Railway's domain system. SSL via Cloudflare.