Sereal Docs

Data model

A conceptual map of Sereal's core tables — what to read, not a schema dump.

This is an orientation map, not the schema itself. The authoritative definitions are in source: the initial schema in SCHEMA.sql and the full, current shape in the ordered supabase/migrations/ sequence. When this page and the migrations disagree, the migrations win.

Core entities

The original spine of the app — everything else hangs off these:

TableWhat it holds
itemsEvery card and comic you own: medium, cost basis, grade, box, disposition. The center of gravity.
vendorsWhere things were bought from. Seeded per-tenant on owner bootstrap.
spend_logSealed-box and other non-itemized spend. Counts toward Total In; pulled cards cost $0 because the box is already logged here.
wishlistCards and comics you're chasing, on the buy side.
dealseBay listings surfaced by polling, with tier and motivation scoring.
sold_logWhat you've sold, for realized P&L.

What later migrations add

The app has grown well beyond the initial schema. Rather than enumerate every table, here are the feature areas whose tables you'll encounter — each was added by a numbered migration:

  • Breaks — group-break cost allocation (break_spots and a rollup view) for Pick-Your-Player / Pick-Your-Team / random breaks.
  • Import batches — provenance for CSV imports (PSA Vault, WhatNot, COMC), linking imported items back to a spend entry.
  • Positions & theses — the decision layer: a thesis on a position drives buy/hold/trim recommendations.
  • Signals — per-sport scoring config and star-player heuristics that feed intake triage and recommendations.
  • Show sessions — the mobile card-show loadout.
  • User settings — per-tenant flags, intent/onboarding state, box definitions.

Accounting rules baked into the schema

Two invariants matter when reading the data:

  • Total In = spend_log total + the total_cost of items whose source is an individual purchase. Cards pulled from a sealed box are $0 (the box is already in spend_log) — don't double-count.
  • Tenant scoping is enforced by Row-Level Security on auth.uid(), and again in application code as defense-in-depth.

Generating types

After applying migrations, regenerate the TypeScript types the app builds against:

npx supabase gen types typescript --local > lib/supabase/types.ts

On this page