Skip to content

feat(render): draw report pages in the browser from the site's data - #18

Merged
psanders merged 1 commit into
mainfrom
feat/data-driven-pages
Nov 5, 2026
Merged

psanders merged 1 commit into
mainfrom
feat/data-driven-pages

Conversation

@psanders

@psanders psanders commented Nov 5, 2026

Copy link
Copy Markdown
Member

What

perfkit render now publishes a data-driven site. Pages are drawn in the browser, when someone views them, from JSON on the same site. Each run's HTML is no longer frozen with the perfkit version that drew it.

New --out layout:

index.html                    shell: latest run (title/description/OG of the newest run)
runs/<id>/index.html          shell per run in the history (rewritten each publish, tiny)
runs/<id>/report.json         copy of the report, so the page's existing report.json link works
data/runs.json                history index (runs.json v1, unchanged schema)
data/runs/<id>/report.json    the report the app draws
app/<version>/app.js          the existing renderer + schemas, bundled by esbuild (IIFE, 264 KB / 76 KB gzip)
  • How the shell picks the run: the shell loads app/<version>/app.js with defer. The app takes the site root as two levels above its own script (document.currentScript.src). The page path relative to that root picks the run: `` or index.html is the latest run (`runs[0]` of `data/runs.json`), and `runs//` (with or without `index.html`) is that run. The app fetches `data/runs.json` and `data/runs//report.json` (with `cache: no-cache`) and validates both with the same Zod schemas as `perfkit validate`. It then calls the unchanged `renderRunPage`. The returned document replaces the shell's ``, and the picker script is re-inserted so it runs once. If drawing fails, the shell shows the error lines in a `role=alert`.
  • Publishing adds this run's data files, rewrites data/runs.json and the shells, and adds the app version. It never reads or rewrites older reports. Every shell pins the current app version, so publishing with a newer perfkit redraws every run.
  • Compatibility: --history still takes any runs.json v1, including the old root runs.json. If a report is missing from data/runs/<id>/, the app falls back to runs/<id>/report.json, so a site in the old layout migrates by rendering once with --history <old runs.json>.
  • npm run build now also writes dist/app/app.js. The CLI ships that file; when run from src with tsx, it bundles on the fly instead.

Visual output unchanged

No markup or styles changed. Tests show the app's document equals renderRunPage output, node for node:

  • jsdom loads each shell from its URL, runs the real bundle, and compares documentElement.outerHTML with the parsed renderRunPage output. This covers every example report form, with and without history, on both the latest and run pages.
  • test/render/app/published.unit.test.ts covers the six reports currently on Routr's gh-pages (test/fixtures/published/, byte for byte, prettier-ignored). They are rendered in sequence into one site, and each is drawn through the bundled app's validation and render path.
  • A manual check in headless Chrome (Playwright) loaded the six published reports and the latest page from a static server: DOM identical, full-page screenshots pixel identical to the old render, no console errors, and the picker opens and navigates.

Notes for publishers

  • Routr's publish step must now pass --history <site>/benchmarks/data/runs.json. The old benchmarks/runs.json is no longer written. docs/github-workflow.md is updated.
  • Keep keep_files (or an equivalent), so older data/ and app/ folders stay.

🤖 Generated with Claude Code

perfkit render now writes a data-driven site: data/runs.json, the run's
data/runs/<id>/report.json, the browser app under app/<version>/app.js
(the existing renderer bundled with esbuild) and small shells
(index.html and runs/<id>/index.html per run) with the run's title,
description and Open Graph tags. The app picks the run from the URL path
and draws the same page renderRunPage drew, so publishing never re-renders
older runs and a newer perfkit redraws every run.
@psanders
psanders merged commit 22b8462 into main Nov 5, 2026
2 checks passed
@psanders psanders mentioned this pull request Nov 5, 2026
@psanders
psanders deleted the feat/data-driven-pages branch November 5, 2026 14:26
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