import type { Metadata } from 'next'; import Link from 'next/link'; import { PageHeader } from '@/components/ui/page-header'; import { Badge } from '@/components/ui/primitives'; import { getCategoryCounts } from '@/lib/queries/markets'; import { getCategoryThumbnails } from '@/lib/queries/assets'; import { Thumb } from '@/components/market/bits'; import { FAMILIES, getCategory } from '@rareindex/taxonomy'; import { fmtNum } from '@/lib/format'; import { INDICES } from '@rareindex/taxonomy'; export const metadata: Metadata = { title: 'Categories', description: 'The RareIndex collectible taxonomy: every family and subcategory tracked, with launch phase and live coverage.' }; export const revalidate = 300; export default async function CategoriesPage() { const counts = await getCategoryCounts(); const thumbs = await getCategoryThumbnails(FAMILIES.flatMap((f) => [f.slug, ...f.children])); const total = (slugs: string[]) => slugs.reduce((a, s) => a + (counts.get(s)?.assets ?? 0), 0); const groups = [1, 2, 3].map((phase) => ({ phase, families: FAMILIES.filter((f) => f.phase === phase) })); return (
{groups.map((g) => (

Phase {g.phase} {g.phase === 1 ? 'Launch wedge' : g.phase === 2 ? 'Next expansion' : 'Full universe'} {g.families.length} families

{g.families.map((f) => { const assets = total([f.slug, ...f.children.flatMap((c) => [c, ...(getCategory(c)?.children ?? [])])]); const idx = INDICES.find((i) => i.ticker === f.index); return (
thumbs.get(c)).find(Boolean)} alt="" size={28} rounded="rounded-md" /> {f.name} {idx ? ( {idx.ticker} ) : null}
{f.description ?

{f.description}

: null} {f.children.length ? (
    {f.children.map((c) => { const n = getCategory(c)!; const cnt = counts.get(c)?.assets ?? 0; return (
  • {n.name} {cnt ? {fmtNum(cnt, { compact: true })} : null}
  • ); })}
) : null}
{assets ? `${fmtNum(assets)} assets` : 'no data yet'} {assets ? ( Browse → ) : ( {f.conditionScale ? `scale: ${f.conditionScale}` : ''} )}
); })}
))}
); }