1import type { Metadata } from 'next';2import Link from 'next/link';3import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table';4import { EntityLink } from '@/components/ui/entity';5import { Container, Note, PageHeader } from '@/components/ui/section';6import { EmptyState, Unavailable } from '@/components/ui/unavailable';7import { api, safe } from '@/lib/api';8import { cn } from '@/lib/cn';9import { fmtAgo, fmtInt, fmtScore, num } from '@/lib/format';10import { routes } from '@/lib/site';1112export const metadata: Metadata = { title: 'AI benchmarks & leaderboards', description: 'Benchmarks with their published results, evaluation configs and current leaders — never compared blindly across configs.', alternates: { canonical: '/benchmarks' } };13export const revalidate = 300;1415export default async function BenchmarksPage({ searchParams }: { searchParams: Promise<{ category?: string }> }) {16 const { category } = await searchParams;17 const res = await safe(api.benchmarks());18 const all = (res?.items ?? []).slice().sort((a, b) => (num(b.result_count) ?? 0) - (num(a.result_count) ?? 0));19 const cats = new Map<string, number>();20 for (const b of all) {21 const c = typeof b.attributes?.category === 'string' ? b.attributes.category : null;22 if (c) cats.set(c, (cats.get(c) ?? 0) + 1);23 }24 const catList = [...cats.entries()].sort((x, y) => y[1] - x[1] || x[0].localeCompare(y[0]));25 const items = category ? all.filter((b) => b.attributes?.category === category) : all;26 const chip = (active: boolean) => cn('inline-flex h-8 items-center gap-1.5 border px-2.5 text-xs whitespace-nowrap', active ? 'border-ink bg-ink text-canvas' : 'border-rule text-ink-2 hover:border-rule-strong hover:text-ink');27 return (28 <Container>29 <PageHeader eyebrow="Benchmarks" title="Benchmarks" lede="Evaluation suites and the results published for them. Each result carries its configuration; leaders are shown per benchmark, not as a composite." aside={res ? <p className="tnum text-sm text-ink-3">{fmtInt(items.length)}{category ? ` of ${fmtInt(all.length)}` : ''} benchmarks</p> : undefined}>30 {catList.length > 0 && (31 <nav aria-label="Category" className="no-scrollbar -mx-4 mt-6 flex gap-1.5 overflow-x-auto px-4 md:mx-0 md:flex-wrap md:px-0">32 <Link href={routes.benchmarks()} className={chip(!category)} aria-current={!category ? 'true' : undefined}>33 All <span className="tnum opacity-70">{fmtInt(all.length)}</span>34 </Link>35 {catList.map(([c, n]) => (36 <Link key={c} href={`/benchmarks?category=${encodeURIComponent(c)}`} className={chip(category === c)} aria-current={category === c ? 'true' : undefined}>37 {c} <span className="tnum opacity-70">{fmtInt(n)}</span>38 </Link>39 ))}40 </nav>41 )}42 </PageHeader>43 <div className="pb-16">44 {!res ? (45 <Unavailable what="Benchmarks" />46 ) : items.length === 0 ? (47 <EmptyState title={category ? `No benchmark in “${category}”` : 'No benchmarks recorded yet'}>{category && <Link href={routes.benchmarks()} className="link">Show all benchmarks</Link>}</EmptyState>48 ) : (49 <>50 <DataTable caption="Benchmarks">51 <thead>52 <tr>53 <Th>Benchmark</Th>54 <Th>Category</Th>55 <Th>Metric</Th>56 <Th num>Results</Th>57 <Th num>Models</Th>58 <Th>Current leader</Th>59 <Th>Updated</Th>60 </tr>61 </thead>62 <tbody>63 {items.length === 0 && <EmptyRow cols={7}>No benchmarks recorded yet.</EmptyRow>}64 {items.map((b) => {65 const a = b.attributes ?? {};66 return (67 <tr key={b.id}>68 <Td primary>69 <Link href={routes.benchmark(b.slug)} className="text-ink hover:text-accent hover:underline">{b.name}</Link>70 {(b.description || typeof a.task === 'string') && <span className="block max-w-md truncate text-xs text-ink-3">{b.description ?? (a.task as string)}</span>}71 </Td>72 <Td label="Category" className="text-ink-2">{typeof a.category === 'string' ? <Link href={`/benchmarks?category=${encodeURIComponent(a.category)}`} className="hover:text-accent">{a.category}</Link> : <span className="text-ink-3">—</span>}</Td>73 <Td label="Metric" className="text-ink-2">74 {typeof a.metric === 'string' ? a.metric : <span className="text-ink-3">—</span>}75 {typeof a.unit === 'string' && a.unit && <span className="text-ink-3"> ({a.unit})</span>}76 </Td>77 <Td num label="Results" className="tnum">{fmtInt(b.result_count)}</Td>78 <Td num label="Models" className="tnum text-ink-2">{fmtInt(b.model_count)}</Td>79 <Td label="Current leader">80 {b.top ? (81 <span>82 <EntityLink e={b.top.model} className="font-medium" /> <span className="tnum text-ink-2">{fmtScore(b.top.score)}{a.unit === '%' ? '%' : ''}</span>83 {b.top.model.organization && <span className="block text-xs text-ink-3">{b.top.model.organization.name}</span>}84 </span>85 ) : (86 <span className="text-ink-3">—</span>87 )}88 </Td>89 <Td label="Updated" className="text-ink-2" title={b.updated_at}>{fmtAgo(b.updated_at)}</Td>90 </tr>91 );92 })}93 </tbody>94 </DataTable>95 <Note className="mt-3">Leader = best current result under the benchmark's default direction (higher or lower is better). Configs differ; open a benchmark for its leaderboard, config filter and per-model history.</Note>96 </>97 )}98 </div>99 </Container>100 );101}102