1import type { Metadata } from 'next';2import Link from 'next/link';3import { PageHeader } from '@/components/ui/page-header';4import { MarketTable } from '@/components/market/market-table';5import { getMarketRows } from '@/lib/queries/markets';6import { listIndices } from '@/lib/queries/indices';7import { fmtNum } from '@/lib/format';89export const metadata: Metadata = { title: 'Markets', description: 'Collectible category markets: index performance, sales, volume, listings, liquidity and market capitalization estimates.' };10export const revalidate = 300;1112export default async function MarketsPage() {13 const [rows, indices] = await Promise.all([getMarketRows(), listIndices()]);14 const active = rows.filter((r) => r.counts.assets > 0);15 const totals = active.reduce((a, r) => ({ assets: a.assets + r.counts.assets, sales: a.sales + r.counts.sales, listings: a.listings + r.counts.listings }), { assets: 0, sales: 0, listings: 0 });16 const published = indices.filter((i) => i.latest).length;17 return (18 <div>19 <PageHeader20 title="Markets"21 description="One row per collectible family. Index and period changes come from category snapshots; counts come live from the canonical tables. Families without data are listed so coverage is transparent."22 meta={23 <>24 <span className="num">{fmtNum(active.length)} families with data · {fmtNum(totals.assets)} assets · {fmtNum(totals.sales)} sales · {fmtNum(totals.listings)} active listings</span>25 <span>·</span>26 <Link href="/rareindex" className="hover:text-fg">27 {published}/{indices.length} indices published28 </Link>29 <span>·</span>30 <Link href="/market-map" className="hover:text-fg">31 Heatmap view →32 </Link>33 </>34 }35 />36 <div className="card overflow-hidden">37 <MarketTable rows={rows} />38 </div>39 <p className="mt-3 text-[11px] leading-relaxed text-subtle">Market capitalization estimates multiply an estimated population by a representative value and are shown only with their confidence label; they are indicative, never precise (§124). Listing prices are not confirmed transactions.</p>40 </div>41 );42}43