Skip to content

Cut bundled JS 91% by lazy-loading explanation text; add SEO metadata#61

Open
MaxGhenis wants to merge 2 commits into
mainfrom
site-perf-seo
Open

Cut bundled JS 91% by lazy-loading explanation text; add SEO metadata#61
MaxGhenis wants to merge 2 commits into
mainfrom
site-perf-seo

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Why

policybench.org currently ships a 3.5MB-gzipped (55MB raw) JS chunk because app/src/data.json is statically imported into the client bundle. Measured on the live site, the main chunk is 3,541,196 bytes compressed — all of it downloaded and parsed before the page is interactive.

85% of that payload is free text, and most of it is redundant: referenceExplanation is 33MB and verified byte-identical across all models for each (scenario, output) case.

What

Performance (main chunk: 3.54MB → 0.30MB gzipped, −91%; 55MB → 10MB raw):

  • New app/scripts/prepare-data.ts runs before next dev/next build and splits data.json into a bundled numeric summary plus per-country explanation sidecars (public/data/explanations-{us,uk}.json, 2.0MB/0.9MB gzipped)
  • referenceExplanation is deduplicated to one string per case (round-trip covered by tests)
  • The scenario explorer fetches its country's sidecar only when the section approaches the viewport (IntersectionObserver, 1200px margin), with loading/error/retry states in the coverage card and detail dialog
  • Leaderboard metric recomputation, the heatmap, sensitivity, and failure modes are untouched — every numeric field stays in the bundle, so SSR output is identical
  • Generated artifacts are gitignored; data.json remains the only artifact benchmark exports write

SEO (the site had no social previews or crawler config):

  • Open Graph + Twitter card metadata with a generated 1200×630 og-image.png (PolicyEngine tokens), metadataBase, canonical URLs on / and /paper
  • sitemap.xml and robots.txt routes

Resilience: error.tsx boundary so a runtime error no longer renders a blank page.

Notes

  • The bundled summary is ASCII-escaped (like Python's json.dump) because Turbopack's dev JSON-module loader mis-parses multi-byte UTF-8 — the module resolves to undefined. Reproduced on Next 16.2.6; next build is unaffected.
  • Verified locally: bun run lint, bun test (13 pass), bun run build, plus a production next start run confirming SSR content, sidecar fetch + merge (coverage card renders real counts), sitemap/robots/OG tags.

Also done outside this PR: repo homepage URL fixed (pointed at dead policybench.vercel.app, now policybench.org), and www.policybench.org (previously 401) now 308-redirects to the apex via project domain config.

🤖 Generated with Claude Code

data.json (57MB raw, 3.5MB gzipped) was statically imported into the
client bundle, so every visitor downloaded and parsed it before the page
became interactive. 85% of it is free text: referenceExplanation alone
is 33MB and repeated verbatim for every model on the same case.

A prepare-data step (wired into dev/build) now splits data.json into:
- src/data-summary.json: every numeric field, bundled (0.3MB gzipped)
- public/data/explanations-{us,uk}.json: deduped reference narratives
  plus per-model explanation/annotation text, fetched only when the
  scenario explorer approaches the viewport

The bundled summary is ASCII-escaped because Turbopack's dev JSON-module
loader mis-parses multi-byte UTF-8 (the module resolves to undefined).

Also:
- Open Graph/Twitter metadata with a generated og-image.png, canonical
  URLs, sitemap.xml, and robots.txt (the site had no social previews or
  crawler configuration)
- error.tsx boundary so runtime failures don't render a blank page
- Round-trip tests for the split/merge in app/tests/explanations.test.ts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
policybench-site Ready Ready Preview, Comment Jun 9, 2026 9:46pm

Request Review

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant