Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
361 changes: 1 addition & 360 deletions src/app/compare/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Metadata } from "next";
import { Fragment } from "react";
import { notFound, redirect } from "next/navigation";
import Link from "next/link";
import { ArrowLeft, ArrowUpRight } from "lucide-react";
Expand All @@ -12,13 +11,12 @@ import {
} from "@/data/compare-pairs";
import { getProviderRegistry } from "@/data/provider-registry";
import { ProviderLogo } from "@/components/provider-logo";
import { fmtUnit, fmtValue, unitSuffix } from "@/lib/format";
import { fmtUnit } from "@/lib/format";
import { capDescription } from "@/lib/seo-text";
import { Breadcrumb } from "@/components/breadcrumb";
import { buildBreadcrumbJsonLd, safeJsonLd } from "@/lib/jsonld";
import { SITE } from "@/data/site";
import { CREATOR_PUBLISHER, DATASET_LICENSE } from "@/lib/dataset-jsonld";
import type { Benchmark } from "@/types/benchmark";
import { CompareBenchCard } from "@/components/compare-bench-card";
import type { CompareBench } from "@/components/compare-bench-card";
import {
Expand Down Expand Up @@ -989,360 +987,3 @@ function ProviderHeader({
);
}

function BenchCard({
bench,
aName,
bName,
}: {
bench: SharedBench;
aName: string;
bName: string;
}) {
return (
<article className="border border-rule rounded-2xl p-5 sm:p-6">
<header className="mb-5 flex flex-wrap items-baseline justify-between gap-2">
<h3 className="display text-base sm:text-lg tracking-tight text-ink leading-tight">
<Link
href={`/benchmarks/${bench.slug}`}
className="hover:underline"
>
{bench.title}
</Link>
</h3>
<span className="text-[10px] uppercase tracking-[0.16em] text-ink-faint shrink-0">
{bench.category}
</span>
</header>

<div className="grid grid-cols-2 gap-3 sm:gap-4">
<AggregatePanel
name={aName}
panel={bench.aResult}
unit={bench.unit}
winner={bench.aggregateWinner === "a"}
loser={bench.aggregateWinner === "b"}
/>
<AggregatePanel
name={bName}
panel={bench.bResult}
unit={bench.unit}
winner={bench.aggregateWinner === "b"}
loser={bench.aggregateWinner === "a"}
/>
</div>

{bench.chainRegionMatrix.length > 0 ? (
<ChainRegionMatrix
entries={bench.chainRegionMatrix}
aName={aName}
bName={bName}
unit={bench.unit}
/>
) : (
<>
{bench.chainBreakdown.length > 0 && (
<BreakdownTable
title="Per chain"
rows={bench.chainBreakdown}
aName={aName}
bName={bName}
unit={bench.unit}
/>
)}
{bench.regionBreakdown.length > 0 && (
<BreakdownTable
title="Per region"
rows={bench.regionBreakdown}
aName={aName}
bName={bName}
unit={bench.unit}
/>
)}
</>
)}

<footer className="mt-5 border-t border-rule pt-3 flex flex-wrap items-center justify-between gap-2 text-[10px] uppercase tracking-[0.16em] text-ink-faint">
<span>Rolling 24h · {bench.metric}</span>
<Link
href={`/api/stat/${bench.slug}`}
className="hover:text-ink-soft normal-case tracking-normal"
>
Raw JSON
</Link>
</footer>
</article>
);
}

function AggregatePanel({
name,
panel,
unit,
winner,
loser,
}: {
name: string;
panel: Panel;
unit: Benchmark["unit"];
winner: boolean;
loser: boolean;
}) {
const hasData = panel.rank > 0 && panel.p50 > 0;
const containerCls = winner
? "border-good/60 bg-good/5"
: loser
? "border-bad/40 bg-bad/5"
: "border-rule bg-surface";
const headlineCls = winner
? "text-good"
: loser
? "text-bad"
: "text-ink";
return (
<div
className={`rounded-xl px-4 py-4 border flex flex-col gap-2 ${containerCls}`}
>
<div className="flex items-baseline justify-between gap-2">
<p className="text-[11px] uppercase tracking-[0.16em] text-ink-muted font-medium">
{name}
</p>
{winner && hasData && (
<span className="text-[10px] font-medium uppercase tracking-[0.16em] text-good">
Leads
</span>
)}
{loser && hasData && (
<span className="text-[10px] font-medium uppercase tracking-[0.16em] text-bad">
Trails
</span>
)}
</div>
{hasData ? (
<>
<p
className={`display text-3xl sm:text-4xl tracking-tight tabular leading-none ${headlineCls}`}
>
{fmtValue(panel.p50, unit)}
<span className="ml-1 text-base text-ink-muted">
{unitSuffix(unit, panel.p50)}
</span>
</p>
<dl className="mt-3 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-[11px] text-ink-muted tabular">
<dt>p99</dt>
<dd className="text-right text-ink-soft">
{fmtUnit(panel.p99, unit)}
</dd>
<dt>rank</dt>
<dd className="text-right text-ink-soft">#{panel.rank}</dd>
{panel.sampleSize ? (
<>
<dt>samples</dt>
<dd className="text-right text-ink-soft">
{Math.round(panel.sampleSize).toLocaleString()}
</dd>
</>
) : null}
</dl>
</>
) : (
<p className="text-sm text-ink-faint">No data in window</p>
)}
</div>
);
}

/** Single flat 2D matrix used when a bench exposes both `chain` and
* `region` dimensions. Rows are grouped per chain (rowspan on the chain
* cell), two sub-rows per chain (one per provider). Columns expand
* across every region observed for the pair plus an aggregate column on
* the right. Each value cell is colored by the per-cell winner so the
* table reads as a heatmap: green = leads here, red = trails. */
function ChainRegionMatrix({
entries,
aName,
bName,
unit,
}: {
entries: ChainRegionEntry[];
aName: string;
bName: string;
unit: Benchmark["unit"];
}) {
const regionMap = new Map<string, string>();
for (const entry of entries) {
for (const r of entry.regionRows) {
if (!regionMap.has(r.value)) regionMap.set(r.value, r.label);
}
}
const regions = Array.from(regionMap.entries()).map(([value, label]) => ({
value,
label,
}));

const valueCell = (win: boolean, lose: boolean, isAggregate = false) => {
const color = win
? "text-good font-medium"
: lose
? "text-bad"
: "text-ink";
return `py-2 px-2 text-right whitespace-nowrap ${isAggregate ? "border-l border-rule" : ""} ${color}`;
};
const emptyCell = (isAggregate = false) =>
`py-2 px-2 text-right text-ink-faint ${isAggregate ? "border-l border-rule" : ""}`;

return (
<div className="mt-6 border-t border-rule pt-4">
<p className="text-[11px] uppercase tracking-[0.18em] text-ink-muted font-medium mb-3">
Per chain · per region
</p>
<div className="overflow-x-auto -mx-5 sm:-mx-6 px-5 sm:px-6">
<table className="w-full text-sm tabular border-collapse">
<thead>
<tr className="text-[10px] uppercase tracking-[0.16em] text-ink-faint border-b border-rule">
<th
scope="col"
className="text-left font-medium py-2 pr-3 sticky left-0 bg-bg z-10"
>
Chain
</th>
<th scope="col" className="text-left font-medium py-2 px-3">
Provider
</th>
{regions.map((r) => (
<th
key={r.value}
scope="col"
className="text-right font-medium py-2 px-2"
>
{r.label}
</th>
))}
<th
scope="col"
className="text-right font-medium py-2 pl-3 pr-1 border-l border-rule"
>
Aggregate
</th>
</tr>
</thead>
<tbody>
{entries.map((entry) => {
const byRegion = new Map(
entry.regionRows.map((r) => [r.value, r] as const),
);
return (
<Fragment key={entry.value}>
<tr className="border-t border-rule">
<th
scope="rowgroup"
rowSpan={2}
className="py-2 pr-3 text-left text-ink-soft font-medium align-top sticky left-0 bg-bg border-r border-rule/60"
>
{entry.label}
</th>
<td className="py-2 px-3 text-[11px] uppercase tracking-[0.14em] text-ink-muted">
{aName}
</td>
{regions.map((r) => {
const row = byRegion.get(r.value);
return row ? (
<td
key={r.value}
className={valueCell(row.aWins, row.bWins)}
>
{fmtUnit(row.aP50, unit)}
</td>
) : (
<td key={r.value} className={emptyCell()}>
-
</td>
);
})}
<td className={valueCell(entry.aWins, entry.bWins, true)}>
{fmtUnit(entry.aP50, unit)}
</td>
</tr>
<tr className="border-b border-rule">
<td className="py-2 px-3 text-[11px] uppercase tracking-[0.14em] text-ink-muted">
{bName}
</td>
{regions.map((r) => {
const row = byRegion.get(r.value);
return row ? (
<td
key={r.value}
className={valueCell(row.bWins, row.aWins)}
>
{fmtUnit(row.bP50, unit)}
</td>
) : (
<td key={r.value} className={emptyCell()}>
-
</td>
);
})}
<td className={valueCell(entry.bWins, entry.aWins, true)}>
{fmtUnit(entry.bP50, unit)}
</td>
</tr>
</Fragment>
);
})}
</tbody>
</table>
</div>
</div>
);
}

function BreakdownTable({
title,
rows,
aName,
bName,
unit,
}: {
title: string;
rows: BreakdownRow[];
aName: string;
bName: string;
unit: Benchmark["unit"];
}) {
return (
<div className="mt-6 border-t border-rule pt-4">
<p className="text-[11px] uppercase tracking-[0.18em] text-ink-muted font-medium mb-3">
{title}
</p>
<div className="overflow-x-auto">
<table className="w-full text-sm tabular">
<thead>
<tr className="text-[10px] uppercase tracking-[0.16em] text-ink-faint border-b border-rule">
<th className="text-left font-medium pb-2 pr-3">
{title === "Per region" ? "Region" : "Chain"}
</th>
<th className="text-right font-medium pb-2 px-3">{aName}</th>
<th className="text-right font-medium pb-2 pl-3">{bName}</th>
</tr>
</thead>
<tbody className="divide-y divide-rule">
{rows.map((row) => (
<tr key={row.value}>
<td className="py-2 pr-3 text-ink-soft">{row.label}</td>
<td
className={`py-2 px-3 text-right ${row.aWins ? "text-good font-medium" : row.bWins ? "text-bad" : "text-ink"}`}
>
{fmtUnit(row.aP50, unit)}
</td>
<td
className={`py-2 pl-3 text-right ${row.bWins ? "text-good font-medium" : row.aWins ? "text-bad" : "text-ink"}`}
>
{fmtUnit(row.bP50, unit)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
Loading