diff --git a/app/globals.css b/app/globals.css index 74da31f..a08c9ec 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,51 +1,474 @@ * { box-sizing: border-box; } -:root { --ink:#070a1a; --body:#36405d; --blue:#4865ff; --line:#dfe3eb; --soft:#f7f8fb; } +:root { + --ink: #070a1a; + --body: #36405d; + --muted: #6c748c; + --blue: #4865ff; + --line: #dfe3eb; + --soft: #f7f8fb; + --softer: #eef1f7; + --claude: #c15f3c; + --claude-soft: #fdf1eb; + --codex: #10a37f; + --codex-soft: #e6f6f0; + --pass: #0f8a5e; + --pass-soft: #e2f4ec; + --fail: #c73a3a; + --fail-soft: #fbe9e9; + --nuance: #a3641c; + --nuance-soft: #fbf1de; +} + html { scroll-behavior: smooth; } -body { margin:0; background:#fff; color:var(--body); font:16px/1.5 Arial, Helvetica, sans-serif; } -a { color:var(--blue); } -img { display:block; max-width:100%; height:auto; } -code, dd { overflow-wrap:anywhere; min-width:0; } -.wrap { width:min(1184px, calc(100% - 48px)); margin:0 auto; } -.site-header { border-bottom:1px solid var(--line); background:#fff; position:sticky; top:0; z-index:10; } -.nav-row { height:64px; display:flex; align-items:center; gap:24px; } -.wordmark { color:var(--ink); text-decoration:none; font-size:19px; font-weight:700; letter-spacing:-.03em; } -.wordmark span { color:var(--blue); } -nav { margin-left:auto; display:flex; gap:18px; } -nav a { color:var(--ink); text-decoration:none; font-size:14px; } -.block { padding:48px 0; border-bottom:1px solid var(--line); } -.mechanical-head { padding-top:64px; } -.label { margin:0 0 12px; font-size:12px; text-transform:uppercase; letter-spacing:.12em; } -h1,h2,h3 { color:var(--ink); line-height:1.2; } -h1 { max-width:900px; font-size:clamp(32px,4vw,48px); margin:0 0 18px; } -h2 { margin:0 0 24px; font-size:26px; } -h3 { margin:0 0 8px; font-size:20px; } -.facts, .mini-facts { margin:0 0 24px; } -.facts div { display:grid; grid-template-columns:180px 1fr; padding:12px 0; border-top:1px solid var(--line); } -dt { font-weight:700; color:var(--ink); } -dd { margin:0; } -.output-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:24px; } -.output { border:1px solid var(--line); padding:18px; min-width:0; background:#fff; } -.output > p { margin:0 0 14px; } -.shot-window { height:560px; overflow:auto; border:1px solid var(--line); background:var(--soft); margin-bottom:10px; } -.shot-window img { width:100%; } -.mini-facts { margin-top:18px; } -.mini-facts div { display:grid; grid-template-columns:110px 1fr; border-top:1px solid var(--line); padding:9px 0; font-size:14px; } -details { margin-top:18px; border:1px solid var(--line); padding:14px; } -summary { color:var(--ink); font-weight:700; cursor:pointer; } -pre { white-space:pre-wrap; overflow:auto; background:var(--soft); padding:18px; font:13px/1.55 ui-monospace, monospace; } -.mobile-shot { margin:14px auto 0; max-width:390px; } -.table-wrap { overflow:auto; border:1px solid var(--line); max-width:100%; } -table { width:100%; border-collapse:collapse; font-size:14px; } -th,td { padding:10px 14px; border-bottom:1px solid var(--line); text-align:left; } -th { color:var(--ink); background:var(--soft); } -.file-list { columns:2; margin:0; padding-left:20px; } -.file-list li { margin:0 0 10px; break-inside:avoid; } -footer { padding:32px 0; } -@media (max-width:700px) { - .wrap { width:calc(100% - 32px); } - nav { display:none; } - .output-grid { grid-template-columns:1fr; } - .shot-window { height:420px; } - .facts div, .mini-facts div { grid-template-columns:1fr; gap:4px; } - .file-list { columns:1; } +body { + margin: 0; + background: #fff; + color: var(--body); + font: 16px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif; + -webkit-font-smoothing: antialiased; +} +a { color: var(--blue); } +img { display: block; max-width: 100%; height: auto; } +code { + overflow-wrap: anywhere; + background: var(--soft); + padding: 1px 5px; + border-radius: 3px; + font: 13px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; +} +dd { overflow-wrap: anywhere; min-width: 0; } + +.wrap { width: min(1184px, calc(100% - 48px)); margin: 0 auto; } + +/* ---------- Site chrome (preserved identity) ---------- */ +.site-header { + border-bottom: 1px solid var(--line); + background: rgba(255,255,255,0.92); + backdrop-filter: saturate(1.4) blur(8px); + position: sticky; + top: 0; + z-index: 20; +} +.nav-row { height: 64px; display: flex; align-items: center; gap: 24px; } +.wordmark { + color: var(--ink); + text-decoration: none; + font-size: 19px; + font-weight: 700; + letter-spacing: -.03em; +} +.wordmark span { color: var(--blue); } +nav { margin-left: auto; display: flex; gap: 22px; } +nav a { color: var(--ink); text-decoration: none; font-size: 14px; } +nav a:hover { color: var(--blue); } + +footer { + padding: 32px 0; + border-top: 1px solid var(--line); + color: var(--muted); + font-size: 13px; +} + +/* ---------- Common section pieces ---------- */ +.block { padding: 72px 0; border-bottom: 1px solid var(--line); } +h1, h2, h3, h4 { color: var(--ink); line-height: 1.15; letter-spacing: -.015em; } +h1 { font-size: clamp(34px, 4.6vw, 54px); margin: 0 0 20px; max-width: 900px; letter-spacing: -.03em; } +h2 { font-size: clamp(24px, 2.6vw, 32px); margin: 0 0 12px; } +h3 { font-size: 18px; margin: 0 0 8px; } +h4 { font-size: 17px; margin: 0 0 8px; } + +.label { + margin: 0 0 16px; + font-size: 12px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: .14em; + color: var(--muted); +} + +.section-head { margin-bottom: 32px; max-width: 780px; } +.section-sub { margin: 0; color: var(--muted); font-size: 16px; } + +/* ---------- Hero ---------- */ +.hero { padding: 72px 0 56px; } +.hero .lede { + max-width: 780px; + font-size: 19px; + line-height: 1.55; + margin: 0 0 40px; + color: var(--body); +} + +.tldr { + display: grid; + grid-template-columns: 1fr 1.6fr; + gap: 0; + border: 1px solid var(--line); + border-radius: 12px; + overflow: hidden; + background: #fff; +} +.tldr-cell { padding: 24px 26px; } +.tldr-cell + .tldr-cell { border-left: 1px solid var(--line); } +.tldr-cell p { margin: 0; color: var(--body); } +.tldr-cell p em { color: var(--ink); font-style: italic; } +.tldr-label { + display: block; + font-size: 11px; + font-weight: 700; + letter-spacing: .12em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: 8px; +} + +.prompt-details { + margin-top: 28px; + border: 1px solid var(--line); + border-radius: 10px; + padding: 14px 18px; + background: #fff; +} +.prompt-details summary { + cursor: pointer; + color: var(--ink); + font-weight: 600; + font-size: 14px; +} +.prompt-details pre { + margin: 14px 0 4px; + padding: 18px; + background: var(--soft); + border-radius: 8px; + overflow: auto; + font: 13px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; + white-space: pre-wrap; +} + +/* ---------- Chips + pills ---------- */ +.chip { + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 12px; + font-weight: 700; + letter-spacing: .02em; + padding: 4px 10px; + border-radius: 999px; + border: 1px solid transparent; + line-height: 1; +} +.chip-claude { background: var(--claude-soft); color: var(--claude); border-color: #f4d6c5; } +.chip-codex { background: var(--codex-soft); color: var(--codex); border-color: #c9ead9; } + +.pill { + display: inline-block; + font-size: 12px; + font-weight: 700; + padding: 3px 10px; + border-radius: 999px; +} +.pill-pass { background: var(--pass-soft); color: var(--pass); } +.pill-fail { background: var(--fail-soft); color: var(--fail); } + +.tag { + display: inline-block; + font-size: 11px; + font-weight: 700; + padding: 3px 9px; + border-radius: 999px; + letter-spacing: .04em; + text-transform: uppercase; +} +.tag-fail { background: var(--fail-soft); color: var(--fail); } +.tag-nuance { background: var(--nuance-soft); color: var(--nuance); } + +/* ---------- Builds (side-by-side screenshots) ---------- */ +.builds { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 24px; +} +.build { + background: #fff; + border: 1px solid var(--line); + border-radius: 14px; + padding: 20px; + min-width: 0; + display: flex; + flex-direction: column; + overflow: hidden; +} +.build-claude { border-top: 3px solid var(--claude); } +.build-codex { border-top: 3px solid var(--codex); } +.build-head { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 14px; +} +.build-checks { + font-size: 13px; + color: var(--muted); + font-weight: 600; +} +.shot { + display: block; + height: 520px; + overflow: auto; + border: 1px solid var(--line); + background: var(--soft); + border-radius: 8px; + margin-bottom: 16px; +} +.shot img { width: 100%; display: block; } +.build-facts { margin: 0 0 12px; } +.build-facts div { + display: grid; + grid-template-columns: 110px 1fr; + gap: 12px; + padding: 10px 0; + border-top: 1px solid var(--line); + font-size: 14px; +} +.build-facts dt { color: var(--muted); font-weight: 600; } +.build-facts dd { margin: 0; color: var(--ink); } +.build-note { margin: 6px 0 0; font-size: 14px; color: var(--body); } + +/* ---------- Differences ---------- */ +.diffs { display: grid; gap: 18px; } +.diff { + border: 1px solid var(--line); + border-radius: 12px; + padding: 22px 24px; + background: #fff; +} +.diff h3 { margin: 0 0 14px; font-size: 17px; } +.diff-body { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-bottom: 14px; +} +.diff-cell { + border-left: 3px solid var(--line); + padding: 4px 0 4px 14px; + min-width: 0; +} +.diff-cell.diff-flagged { border-left-color: var(--fail); } +.diff-cell p { margin: 6px 0 0; color: var(--ink); font-size: 15px; } +.diff-takeaway { + margin: 0; + padding-top: 14px; + border-top: 1px dashed var(--line); + color: var(--muted); + font-size: 14px; + font-style: italic; +} + +/* ---------- Scores ---------- */ +.score-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-bottom: 32px; +} +.score { + padding: 24px 28px; + border-radius: 14px; + border: 1px solid var(--line); + background: #fff; + display: flex; + flex-direction: column; + gap: 8px; +} +.score-claude { border-top: 3px solid var(--claude); } +.score-codex { border-top: 3px solid var(--codex); } +.score-big { + font-size: 44px; + font-weight: 800; + color: var(--ink); + line-height: 1; + letter-spacing: -.03em; +} +.score-big span { font-size: 22px; color: var(--muted); font-weight: 600; margin-left: 4px; } +.score-sub { color: var(--muted); font-size: 14px; } + +.failures h3 { font-size: 18px; margin: 0 0 14px; } +.failure-cards { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-bottom: 32px; +} +.failure { + padding: 20px 22px; + border: 1px solid var(--line); + border-radius: 12px; + background: #fff; +} +.failure header { + display: flex; + gap: 10px; + align-items: center; + margin-bottom: 10px; +} +.failure h4 { margin: 6px 0 8px; } +.failure p { margin: 0; font-size: 14px; } + +.full-checks { + border: 1px solid var(--line); + border-radius: 10px; + padding: 14px 18px; + background: #fff; +} +.full-checks summary { + cursor: pointer; + color: var(--ink); + font-weight: 600; + font-size: 14px; +} +.table-wrap { + overflow: auto; + border: 1px solid var(--line); + border-radius: 8px; + margin-top: 14px; +} +table { width: 100%; border-collapse: collapse; font-size: 14px; } +th, td { padding: 10px 14px; border-bottom: 1px solid var(--line); text-align: left; } +th { color: var(--ink); background: var(--soft); font-weight: 700; } +tbody th { background: #fff; font-weight: 500; color: var(--ink); } +tbody tr:last-child th, tbody tr:last-child td { border-bottom: 0; } + +/* ---------- Mobile row ---------- */ +.mobile-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 28px; +} +.mobile-fig { margin: 0; } +.mobile-fig figcaption { margin-bottom: 12px; } +.mobile-frame { + max-width: 340px; + margin: 0 auto; + border: 12px solid #0e131f; + border-radius: 28px; + overflow: hidden; + background: #0e131f; + box-shadow: 0 20px 40px rgba(15, 22, 40, 0.08); +} +.mobile-frame img { display: block; width: 100%; height: 620px; object-fit: cover; object-position: top; } + +/* ---------- Under the hood ---------- */ +.hood-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} +.metric { + border: 1px solid var(--line); + border-radius: 12px; + padding: 20px 22px; + background: #fff; + min-width: 0; +} +.metric h3 { + margin: 0 0 14px; + font-size: 12px; + font-weight: 700; + letter-spacing: .12em; + text-transform: uppercase; + color: var(--muted); +} +.metric-row { + display: flex; + flex-direction: column; + gap: 10px; +} +.metric-row > div { + display: flex; + align-items: center; + gap: 10px; + justify-content: space-between; +} +.metric-val { + color: var(--ink); + font-weight: 600; + font-size: 15px; + text-align: right; + overflow-wrap: anywhere; + min-width: 0; +} +.metric-foot { + margin: 14px 0 0; + font-size: 12px; + color: var(--muted); + border-top: 1px dashed var(--line); + padding-top: 10px; +} + +/* ---------- Interpretation ---------- */ +.reads { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 20px; +} +.read { + padding: 22px 24px; + border: 1px solid var(--line); + border-radius: 12px; + background: #fff; +} +.read h3 { margin: 0 0 10px; font-size: 17px; } +.read p { margin: 0; font-size: 15px; } + +/* ---------- Raw evidence ---------- */ +.facts { margin: 0 0 24px; } +.facts div { + display: grid; + grid-template-columns: 180px 1fr; + padding: 12px 0; + border-top: 1px solid var(--line); + gap: 16px; +} +.facts div:last-child { border-bottom: 1px solid var(--line); } +.facts dt { font-weight: 700; color: var(--ink); } +.facts dd { margin: 0; } +.file-list { columns: 2; column-gap: 36px; margin: 0 0 24px; padding-left: 20px; } +.file-list li { margin: 0 0 10px; break-inside: avoid; } +.limits { + border: 1px solid var(--line); + border-radius: 10px; + padding: 14px 18px; + background: #fff; +} +.limits summary { cursor: pointer; color: var(--ink); font-weight: 600; font-size: 14px; } +.limits ul { margin: 12px 0 0; padding-left: 20px; font-size: 14px; } +.limits li { margin-bottom: 8px; } + +/* ---------- Responsive ---------- */ +@media (max-width: 900px) { + .wrap { width: calc(100% - 32px); } + .block { padding: 56px 0; } + .tldr { grid-template-columns: 1fr; } + .tldr-cell + .tldr-cell { border-left: 0; border-top: 1px solid var(--line); } + .builds, .diff-body, .score-row, .failure-cards, .mobile-row, .reads { grid-template-columns: 1fr; } + .hood-grid { grid-template-columns: 1fr 1fr; } + .shot { height: 420px; } + .facts div { grid-template-columns: 1fr; gap: 4px; } + .file-list { columns: 1; } + nav { gap: 14px; } + .diff-cell { padding-left: 12px; } + .mobile-frame img { height: 520px; } +} + +@media (max-width: 560px) { + nav a:not(:last-child) { display: none; } + .hood-grid { grid-template-columns: 1fr; } + h1 { font-size: 32px; } + .hero .lede { font-size: 17px; } + .score-big { font-size: 36px; } + .shot { height: 320px; } + .mobile-frame { max-width: 100%; } + .mobile-frame img { height: 460px; } } diff --git a/app/layout.tsx b/app/layout.tsx index ec9d266..f817df8 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,8 +2,8 @@ import type { Metadata } from "next"; import "./globals.css"; export const metadata: Metadata = { - title: "Raw case-study evidence | WhichBuildWon", - description: "A neutral fixture exposing recorded evidence from a completed WhichBuildWon experiment.", + title: "Same brief. Two Relays. | WhichBuildWon case study", + description: "Claude Code and Codex were given the same 669-byte brief for a Relay SaaS landing page. See what each built, what the checks say, and where they differ.", }; export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { diff --git a/app/page.tsx b/app/page.tsx index 9c306ea..01b5ea5 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,124 +1,505 @@ import evidence from "../public/evidence/raw-run/results.json"; -const links = [ +type CheckKey = keyof (typeof evidence.contestants.claude.grader.checks); + +const claude = evidence.contestants.claude; +const codex = evidence.contestants.codex; + +const rawFiles: Array<[string, string]> = [ ["Frozen results JSON", "/evidence/raw-run/results.json"], - ["Original exact prompt", "/evidence/raw-run/prompt.txt"], + ["Original prompt (SHA-256 verified)", "/evidence/raw-run/prompt.txt"], + ["Evidence manifest", "/evidence/raw-run/manifest.json"], + ["Run validation", "/evidence/raw-run/validation.json"], ["Claude grader JSON", "/evidence/raw-run/claude/grader.json"], ["Codex grader JSON", "/evidence/raw-run/codex/grader.json"], ["Claude source diff", "/evidence/raw-run/claude/final.diff"], ["Codex source diff", "/evidence/raw-run/codex/final.diff"], - ["Claude run log", "/evidence/raw-run/claude/contestant.stdout.log"], - ["Codex run log", "/evidence/raw-run/codex/contestant.stdout.log"], - ["Run validation", "/evidence/raw-run/validation.json"], - ["Evidence manifest", "/evidence/raw-run/manifest.json"], + ["Claude run log", "/evidence/raw-run/claude/contestant-run.json"], + ["Codex run log", "/evidence/raw-run/codex/contestant-run.json"], + ["Claude final git status", "/evidence/raw-run/claude/final-git-status.txt"], + ["Codex final git status", "/evidence/raw-run/codex/final-git-status.txt"], + ["Claude rendered HTML snapshot", "/evidence/raw-run/claude/rendered-page-snapshot.html"], + ["Claude desktop screenshot", "/evidence/raw-run/claude/screenshots/desktop.png"], + ["Codex desktop screenshot", "/evidence/raw-run/codex/screenshots/desktop.png"], + ["Claude mobile screenshot", "/evidence/raw-run/claude/screenshots/mobile.png"], + ["Codex mobile screenshot", "/evidence/raw-run/codex/screenshots/mobile.png"], ]; -const contestants = [ - { - key: "claude", - name: "Claude Code", - desktop: "/evidence/claude-desktop.png", - mobile: "/evidence/claude-mobile.png", - result: evidence.contestants.claude, - }, - { - key: "codex", - name: "Codex", - desktop: "/evidence/codex-desktop.png", - mobile: "/evidence/codex-mobile.png", - result: evidence.contestants.codex, - }, -] as const; +// Human-friendly labels for deterministic checks. +const checkLabels: Record = { + production_build_success: "Production build succeeds", + typescript_success: "TypeScript compiles", + page_loads: "Page returns HTTP 200", + navigation_exists: "Navigation exists", + hero_exists: "Hero exists", + primary_cta_exists: "Primary CTA exists", + social_proof_exists: "Social proof section", + three_feature_sections_exist: "Three feature sections", + roi_calculator_exists: "ROI calculator exists", + roi_calculator_changes_output: "ROI calculator updates output", + pricing_section_exists: "Pricing section exists", + three_pricing_plans_exist: "Three pricing plans (heuristic)", + faq_exists: "FAQ section", + footer_exists: "Footer", + no_broken_links: "No placeholder / broken links", + accessible_buttons_and_form_controls: "Accessible buttons & form controls", + desktop_renders: "Desktop screenshot renders", + mobile_renders: "Mobile screenshot renders", + mobile_no_material_horizontal_overflow: "No mobile horizontal overflow", + no_browser_console_errors: "No browser console errors", +}; + +function checkStatus(passed: boolean) { + return passed ? "pass" : "fail"; +} + +function formatMinutes(ms: number) { + const minutes = Math.floor(ms / 60000); + const seconds = Math.round((ms % 60000) / 1000); + return `${minutes}m ${seconds.toString().padStart(2, "0")}s`; +} + +function formatOptionalCost(v: number | null, fallback = "—") { + return typeof v === "number" ? `$${v.toFixed(2)}` : fallback; +} + +function formatOptionalNumber(v: number | null, fallback = "—") { + return typeof v === "number" ? String(v) : fallback; +} export default function Home() { + const claudeH1 = claude.grader.measurements.desktop_dom.hero.h1; + const codexH1 = codex.grader.measurements.desktop_dom.hero.h1; + const claudeChecks = claude.grader.checks as Record; + const codexChecks = codex.grader.checks as Record; + const brokenLinkCount = claude.grader.measurements.desktop_dom.broken_links.length; + return ( <>
WhichBuildWon
+
-
-

Case-study fixture · raw evidence

-

We gave Claude and Codex the exact same raw experiment evidence. Which one made the result easier to understand?

-

This page exposes the completed Relay landing-page run without an editorial conclusion or designed narrative.

-
+ {/* ----------- HERO / TL;DR ----------- */} +
+

Case study · one-shot build-off

+

Same brief. Two Relays.

+

+ Claude Code and Codex were each given the same 669-byte prompt asking for a polished + responsive SaaS landing page for a fictional product called Relay. Neither could ask + questions. Both had to make every product and design decision on their own. +

-
-

Original experiment record

-
-
Question
{evidence.experiment_question}
-
Starting commit
{evidence.starting_git_commit}
-
Prompt SHA-256
{evidence.prompt_sha256}
-
Method
{evidence.methodology}
-
-
- Original task prompt +
+
+ Question +

{evidence.experiment_question}

+
+
+ Result at a glance +

+ Both models produced a working, responsive landing page that built cleanly, typechecked, + served HTTP 200 without console errors, and included every requested section. The + interesting differences are stylistic, structural, and in how each interpreted the words + “no broken links.” +

+
+
+ +
+ Read the exact prompt both models received
{evidence.exact_shared_brief}
-
-

Recorded contestant outputs

-
- {contestants.map((contestant) => ( -
-

{contestant.name}

-

Desktop screenshot from the completed run.

-
- {`${contestant.name} -
- Open full desktop screenshot -
-
Checks
{contestant.result.grader.summary.passed}/{contestant.result.grader.summary.total} passed
-
Failures
{contestant.result.grader.summary.failed.length ? contestant.result.grader.summary.failed.join(", ") : "None recorded"}
-
Elapsed
{(contestant.result.duration_ms / 1000).toFixed(1)} seconds
-
CLI model record
{contestant.result.model || "Not available"}
+ {/* ----------- WHAT EACH BUILT ----------- */} +
+
+

What each one actually built

+

+ Desktop screenshots captured by Playwright at the end of each run. Click any image for the full-page capture. +

+
+ +
+ {[ + { + key: "claude", + name: "Claude Code", + accent: "claude", + desktop: "/evidence/claude-desktop.png", + mobile: "/evidence/claude-mobile.png", + h1: claudeH1, + cta: claude.grader.measurements.desktop_dom.hero.primary_cta_name, + title: claude.grader.measurements.desktop_dom.title, + data: claude, + note: "Dark hero, one-panel product screen, three named plans (Free / $29 / $79).", + }, + { + key: "codex", + name: "Codex", + accent: "codex", + desktop: "/evidence/codex-desktop.png", + mobile: "/evidence/codex-mobile.png", + h1: codexH1, + cta: codex.grader.measurements.desktop_dom.hero.primary_cta_name, + title: codex.grader.measurements.desktop_dom.title, + data: codex, + note: "Cream palette, hand-built dashboard mock in the hero, plans priced $19 / $49 / $149.", + }, + ].map((b) => ( +
+
+ {b.name} + + {b.data.grader.summary.passed}/{b.data.grader.summary.total} checks passed + +
+ + {`${b.name} + +
+
Page title
{b.title}
+
Hero H1
“{b.h1}”
+
Primary CTA
“{b.cta}”
-
- Mobile screenshot - {`${contestant.name} -
+

{b.note}

))}
+ {/* ----------- KEY DIFFERENCES ----------- */} +
+
+

The differences that actually matter

+

+ Everything below comes from the recorded run — DOM measurements, git diffs, timing, and grader results. +

+
+ +
+ + + + + + +
+
+ + {/* ----------- DETERMINISTIC CHECKS ----------- */} +
+
+

The deterministic checks

+

+ Twenty structural, behavioral, and rendering checks were run against each build. Both cleared build, + typecheck, HTTP 200, console-error, accessibility, and mobile-overflow checks. Two checks split the field. +

+
+ +
+
+ Claude Code + {claude.grader.summary.passed}/{claude.grader.summary.total} + passed +
+
+ Codex + {codex.grader.summary.passed}/{codex.grader.summary.total} + passed +
+
+ +
+

Where they diverged

+
+
+
+ Claude + Failed +
+

No placeholder / broken links

+

+ The grader flagged {brokenLinkCount} anchor tags with href="#". + Nothing was 404-broken — Claude used # as a placeholder for future destinations rather + than wiring links to real page sections. Codex used real intra-page anchors and passed the same check. +

+
+
+
+ Claude + Failed (heuristic miss) +
+

Three pricing plans

+

+ The grader counted 0 plans and marked this failed — but the rendered HTML snapshot + shows Claude did ship three tiers (Free, $29, $79) using .pricing-card markup the + heuristic didn't recognize. Listed as a fail for accuracy; treat as a caveat about deterministic + DOM detection rather than a missing feature. +

+
+
+
+ +
+ All twenty deterministic checks, side by side +
+ + + + {evidence.deterministic_comparison.map((row) => { + const label = checkLabels[row.check] ?? row.check; + return ( + + + + + + ); + })} + +
CheckClaude CodeCodex
{label}{row.claude.passed ? "Pass" : "Fail"}{row.codex.passed ? "Pass" : "Fail"}
+
+
+
+ + {/* ----------- MOBILE ----------- */}
-

Deterministic check comparison

-
- - - - {evidence.deterministic_comparison.map((row) => ( - - - - - - ))} - -
CheckClaude CodeCodex
{row.check}{row.claude?.passed ? "Pass" : "Fail"}{row.codex?.passed ? "Pass" : "Fail"}
+
+

On a phone

+

+ Both pages measured 0 pixels of horizontal overflow at a 390 px viewport. + Content density and visual polish differ; layout correctness does not. +

+
+
+
+
Claude
+
Claude mobile screenshot
+
+
+
Codex
+
Codex mobile screenshot
+
+ {/* ----------- UNDER THE HOOD ----------- */} +
+
+

Under the hood

+

+ Runtime metadata as recorded by each CLI. Codex's CLI did not expose a cost or model field in this + version, so those cells are honestly empty rather than guessed. +

+
+
+ + + + + + +
+
+ + {/* ----------- INTERPRETATION ----------- */} +
+
+

What this one experiment suggests

+
+
+
+

Both models can meet the brief.

+

+ Every hard requirement in the prompt — Next.js, TypeScript, responsive layout, hero, social proof, + three features, ROI calculator, pricing, FAQ, footer, accessible controls, clean build — was met by + both. Neither produced console errors or mobile overflow. +

+
+
+

They interpret ambiguity differently.

+

+ “No broken links” is a great example. Codex read that literally and wired every anchor to a + real destination. Claude filled the requirement with # placeholders, which is idiomatic in + agency work but fails the strictest reading of the brief. +

+
+
+

Structure and effort diverge more than function.

+

+ Claude spent more time and more tokens, split work into a component tree, and produced substantially + more CSS. Codex kept everything in three files with denser, more compact styling. The user-visible + surface areas both cover the brief; the source shapes are very different. +

+
+
+

Deterministic checks are supporting evidence, not a verdict.

+

+ Claude's pricing was flagged missing when it was in fact present. Treat pass/fail counts as a + floor, and lean on the screenshots and diffs when the two disagree. +

+
+
+
+ + {/* ----------- RAW EVIDENCE ----------- */}
-

Other recorded evidence

+
+

Raw evidence & methodology

+

+ Every claim above is drawn from the files below. The starting commit, exact prompt bytes, and prompt SHA-256 + are pinned so this run is reproducible. +

+
+ +
+
Starting commit
{evidence.starting_git_commit}
+
Prompt SHA-256
{evidence.prompt_sha256}
+
Run date
{new Date(evidence.run_date).toUTCString()}
+
Method
{evidence.methodology}
+
+
    - {links.map(([label, href]) =>
  • {label}
  • )} + {rawFiles.map(([label, href]) => ( +
  • {label}
  • + ))}
-
- Recorded limitations -
    {[...evidence.limitations, ...(evidence.evidence_limitations || [])].map((item) =>
  • {item}
  • )}
+ +
+ Recorded limitations we are being transparent about +
    + {[...evidence.limitations, ...(evidence.evidence_limitations || [])].map((item) => ( +
  • {item}
  • + ))} +
-
WhichBuildWon · neutral experiment fixture
+ +
+
WhichBuildWon · neutral experiment fixture
+
); } + +function DiffRow({ + title, + claudeValue, + codexValue, + takeaway, + flag, +}: { + title: string; + claudeValue: string; + codexValue: string; + takeaway: string; + flag?: "claude" | "codex"; +}) { + return ( +
+

{title}

+
+
+ Claude +

{claudeValue}

+
+
+ Codex +

{codexValue}

+
+
+

{takeaway}

+
+ ); +} + +function MetricCard({ + label, + claude, + codex, + footnote, +}: { + label: string; + claude: string; + codex: string; + footnote?: string; +}) { + return ( +
+

{label}

+
+
Claude{claude}
+
Codex{codex}
+
+ {footnote &&

{footnote}

} +
+ ); +}