"use client"; import { useState, useEffect } from "react"; import { Badge } from "@cloudflare/kumo/components/badge"; import { Table } from "@cloudflare/kumo/components/table"; import { formatMs, formatBytes, speedup, sizeReduction, isImprovement, RUNNER_LABELS, } from "./format"; // ─── Types ─────────────────────────────────────────────────────────────────── interface RunnerResult { runner: string; build_time_mean: number | null; build_time_stddev: number | null; build_time_min: number | null; build_time_max: number | null; bundle_size_raw: number | null; bundle_size_gzip: number | null; bundle_file_count: number | null; dev_cold_start_ms: number | null; dev_peak_rss_kb: number | null; platform: string | null; arch: string | null; node_version: string | null; cpu_count: number | null; run_count: number | null; commit_message: string; commit_date: string; run_date: string; } // ─── Component ─────────────────────────────────────────────────────────────── export function CommitDetail({ sha }: { sha: string }) { const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(`/api/commit/${sha}`) .then((res) => { if (!res.ok) throw new Error(res.status === 404 ? "Commit not found" : `HTTP ${res.status}`); return res.json(); }) .then((d) => { setData(d); setLoading(false); }) .catch((err) => { setError(err.message); setLoading(false); }); }, [sha]); if (loading) { return
Loading...
; } if (error) { return (
{error}
); } if (data.length === 0) { return
No results for this commit.
; } const first = data[0]; const nextjs = data.find((d) => d.runner === "nextjs"); return (
{/* Commit header */}

{sha}

{first.run_count} run{first.run_count !== 1 ? "s" : ""}
{first.commit_message && (

{first.commit_message}

)}
Committed: {new Date(first.commit_date).toLocaleString()} Benchmarked: {new Date(first.run_date).toLocaleString()} {first.platform && ( {first.platform}/{first.arch} · Node {first.node_version} ·{" "} {first.cpu_count} CPUs )}
{/* Build Time */} Framework Mean StdDev Min Max vs Next.js {data.map((r) => ( {RUNNER_LABELS[r.runner] || r.runner} {formatMs(r.build_time_mean)} {r.build_time_stddev !== null ? `\u00b1${formatMs(r.build_time_stddev)}` : "-"} {formatMs(r.build_time_min)} {formatMs(r.build_time_max)} {r.runner === "nextjs" ? ( baseline ) : (() => { const label = speedup(nextjs?.build_time_mean ?? null, r.build_time_mean); return label ? ( {label} ) : "-"; })()} ))}
{/* Client Bundle Size */} Framework Files Raw Gzipped vs Next.js (gzip) {data.map((r) => ( {RUNNER_LABELS[r.runner] || r.runner} {r.bundle_file_count ?? "-"} {formatBytes(r.bundle_size_raw)} {formatBytes(r.bundle_size_gzip)} {r.runner === "nextjs" ? ( baseline ) : (() => { const label = sizeReduction(nextjs?.bundle_size_gzip ?? null, r.bundle_size_gzip); return label ? ( {label} ) : "-"; })()} ))}
{/* Dev Cold Start */} Framework Mean Cold Start Peak RSS vs Next.js {data.map((r) => ( {RUNNER_LABELS[r.runner] || r.runner} {formatMs(r.dev_cold_start_ms)} {r.dev_peak_rss_kb ? `${Math.round(r.dev_peak_rss_kb / 1024)} MB` : "-"} {r.runner === "nextjs" ? ( baseline ) : (() => { const label = speedup(nextjs?.dev_cold_start_ms ?? null, r.dev_cold_start_ms); return label ? ( {label} ) : "-"; })()} ))}
); } function MetricSection({ title, children }: { title: string; children: React.ReactNode }) { return (

{title}

{children}
); }