Skip to content

Add a page search to the top of the left menu - #1024

Merged
MDA2AV merged 1 commit into
mainfrom
nav-page-search
Jul 24, 2026
Merged

Add a page search to the top of the left menu#1024
MDA2AV merged 1 commit into
mainfrom
nav-page-search

Conversation

@MDA2AV

@MDA2AV MDA2AV commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Closes #970. The Hextra theme's search went away with Hugo, and with it the only way to find a test specification by name: the board's existing search box filters framework rows, so a query like "prior-knowledge" or "MTU" matched nothing anywhere on the site. 124 Knowledge Base pages were reachable only by walking the tree.

Search covers the Knowledge Base by title AND full body text, plus every leaderboard destination (28 profile views and the 6 composite scopes), so "h2c" reaches both the JSON (h2c) board and its implementation page.

Results are ranked: a title hit outranks a body hit, an exact title match wins outright, and views float slightly above docs since they are the cheaper landing. Multi-word queries are AND (every term must appear somewhere), each doc hit carries a breadcrumb and a snippet with the match highlighted, and the list caps at 25.

No dependency and no index file. docs.js already ships every page's rendered HTML, so the index is built from what is already in memory, on the first keystroke rather than at load -- 158 entries over 0.24 MB of text in ~5 ms. Tags are stripped with a regex rather than by assigning to a detached innerHTML, because that would fetch any the docs grow later.

Two structural details:

buildNav() now clears #navTree instead of #nav. The search box is static markup above it, so it survives the nav rebuild that every navigation triggers -- otherwise typing would lose focus as soon as results changed.

On mobile the tree is still hidden in favour of the existing select, but .nav is no longer display:none, so the search bar itself stays reachable.

Keyboard: arrows move the selection, Enter opens, Escape clears. Opening a result clears the query first, so the user lands on a normal menu showing where they now are. Colours come from the existing theme variables, so light and dark both work.

Verified end-to-end in headless Chrome against the real data files: the tree builds into its new container, typing "fortunes" yields 6 hits with the tree hidden and the first hit selected, ArrowDown moves the selection, clicking a docs hit renders the page and rewrites the URL to #doc=test-profiles/h1/isolated/fortunes (so results stay deep-linkable), the input clears and the tree comes back, a nonsense query shows the empty state, and Escape restores everything. Checked at 1400px and 400px.

Description


PR Commands — comment on this PR to trigger (requires collaborator approval):

Command Description
/benchmark -f <framework> Run all benchmark tests
/benchmark -f <framework> -t <test> Run a specific test
/benchmark -f <framework> --save Run and save results (updates leaderboard on merge)

Always specify -f <framework>. Results are automatically compared against the current leaderboard.


Run benchmarks locally

You can validate and benchmark your framework locally with the lite script — no CPU pinning, fixed connection counts, all load generators run in Docker.

./scripts/validate.sh <framework>
./scripts/benchmark-lite.sh <framework> baseline
./scripts/benchmark-lite.sh --load-threads 4 <framework>

Requirements: Docker Engine on Linux. Load generators (gcannon, h2load, h2load-h3, wrk, ghz) are built as self-contained Docker images on first run.

Closes #970. The Hextra theme's search went away with Hugo, and with it the
only way to find a test specification by name: the board's existing search
box filters framework rows, so a query like "prior-knowledge" or "MTU"
matched nothing anywhere on the site. 124 Knowledge Base pages were
reachable only by walking the tree.

Search covers the Knowledge Base by title AND full body text, plus every
leaderboard destination (28 profile views and the 6 composite scopes), so
"h2c" reaches both the JSON (h2c) board and its implementation page.

Results are ranked: a title hit outranks a body hit, an exact title match
wins outright, and views float slightly above docs since they are the
cheaper landing. Multi-word queries are AND (every term must appear
somewhere), each doc hit carries a breadcrumb and a snippet with the match
highlighted, and the list caps at 25.

No dependency and no index file. docs.js already ships every page's
rendered HTML, so the index is built from what is already in memory, on
the first keystroke rather than at load -- 158 entries over 0.24 MB of
text in ~5 ms. Tags are stripped with a regex rather than by assigning to
a detached innerHTML, because that would fetch any <img> the docs grow
later.

Two structural details:

buildNav() now clears #navTree instead of #nav. The search box is static
markup above it, so it survives the nav rebuild that every navigation
triggers -- otherwise typing would lose focus as soon as results changed.

On mobile the tree is still hidden in favour of the existing select, but
.nav is no longer display:none, so the search bar itself stays reachable.

Keyboard: arrows move the selection, Enter opens, Escape clears. Opening a
result clears the query first, so the user lands on a normal menu showing
where they now are. Colours come from the existing theme variables, so
light and dark both work.

Verified end-to-end in headless Chrome against the real data files: the
tree builds into its new container, typing "fortunes" yields 6 hits with
the tree hidden and the first hit selected, ArrowDown moves the selection,
clicking a docs hit renders the page and rewrites the URL to
#doc=test-profiles/h1/isolated/fortunes (so results stay deep-linkable),
the input clears and the tree comes back, a nonsense query shows the empty
state, and Escape restores everything. Checked at 1400px and 400px.
@MDA2AV
MDA2AV merged commit cfbd513 into main Jul 24, 2026
MDA2AV added a commit to Kaliumhexacyanoferrat/HttpArena that referenced this pull request Jul 24, 2026
Resolves the conflict GitHub reported against this PR. Nothing conflicted
textually: the PR renames site/static/new-leaderboard/index.html to
site/leaderboard/index.html while main modified it in place, and GitHub's
mergeability check does not apply rename detection, so it reported the pair
as a modify/delete conflict. `git merge-tree --write-tree` exits 0 and both
merge directions are clean locally.

Carries in the three changes main made to that file since this branch forked
at 6bcf729:

  MDA2AV#1024  the Knowledge Base page search in the left menu (#navq, #navTree,
         buildSearchIndex) — note buildNav() now clears #navTree, not #nav
  MDA2AV#1025  the .tsq-* type square colours, which MDA2AV#1017 had deleted by way of a
         shared CSS line
  MDA2AV#1018  the type-rules "standard" attribute rename in the generator

all of which land in the renamed file and the renamed generator.
MDA2AV added a commit to Kaliumhexacyanoferrat/HttpArena that referenced this pull request Jul 24, 2026
Three things, all in service of this PR's goal of making the docs indexable.

1. Authored title + description for all 123 pages

The generator derived the meta description from each page's first <p>. That
opening line is often a cross-reference ("Same workload as JSON Processing,
but…"), which reads as boilerplate in a search result. Descriptions are now
authored in frontmatter; the scrape stays as the fallback for any page that
lacks one.

Titles were worse: 123 pages shared only 71 distinct titles, because 26 are
called "Implementation Guidelines" and 26 more "Validation". As <title> tags
those compete with each other for the same query, and a result reading just
"Validation" says nothing about which test it covers. A new `seo_title`
frontmatter key overrides the tag without touching the sidebar label, so
navigation still reads "Validation" while the page is titled "Baseline
Throughput Benchmark — Validation Checks".

Result: 123 unique titles, 123 unique descriptions, 81-153 characters each.
The SPA index page's own title and description are untouched.

2. The board's page search had been left indexing nothing

MDA2AV#1024 added Knowledge Base search to the left menu, built from window.LB_DOCS
— the docs.js blob. This PR stops generating docs.js, so LB_DOCS is always {}
and the search silently degraded to the 34 leaderboard views: no
documentation results at all, which is the exact complaint MDA2AV#970 was opened
about.

Reverting to docs.js would undo the payload win, so the generator now emits
search.js instead: the same pages as plain text, prepared server-side. It is
266 KB against docs.js's 427 KB, needs no client-side tag stripping, and each
entry carries the URL of its real page, so a hit navigates to /docs/<id>/
rather than rendering in place. The authored description is indexed too.

stripHtml() and docCrumb() go with it — both existed only to process the
retired HTML blob.

3. deploy.yml ships search.js alongside data.js.

Verified by regenerating: 123 static pages, 123 unique titles and
descriptions with no page over 160 characters, a 123-entry search index, and
a 124-URL sitemap.
MDA2AV added a commit that referenced this pull request Jul 24, 2026
* Remove old leaderboar and optimize SEO

* Add per-page SEO metadata, and keep the board's page search working

Three things, all in service of this PR's goal of making the docs indexable.

1. Authored title + description for all 123 pages

The generator derived the meta description from each page's first <p>. That
opening line is often a cross-reference ("Same workload as JSON Processing,
but…"), which reads as boilerplate in a search result. Descriptions are now
authored in frontmatter; the scrape stays as the fallback for any page that
lacks one.

Titles were worse: 123 pages shared only 71 distinct titles, because 26 are
called "Implementation Guidelines" and 26 more "Validation". As <title> tags
those compete with each other for the same query, and a result reading just
"Validation" says nothing about which test it covers. A new `seo_title`
frontmatter key overrides the tag without touching the sidebar label, so
navigation still reads "Validation" while the page is titled "Baseline
Throughput Benchmark — Validation Checks".

Result: 123 unique titles, 123 unique descriptions, 81-153 characters each.
The SPA index page's own title and description are untouched.

2. The board's page search had been left indexing nothing

#1024 added Knowledge Base search to the left menu, built from window.LB_DOCS
— the docs.js blob. This PR stops generating docs.js, so LB_DOCS is always {}
and the search silently degraded to the 34 leaderboard views: no
documentation results at all, which is the exact complaint #970 was opened
about.

Reverting to docs.js would undo the payload win, so the generator now emits
search.js instead: the same pages as plain text, prepared server-side. It is
266 KB against docs.js's 427 KB, needs no client-side tag stripping, and each
entry carries the URL of its real page, so a hit navigates to /docs/<id>/
rather than rendering in place. The authored description is indexed too.

stripHtml() and docCrumb() go with it — both existed only to process the
retired HTML blob.

3. deploy.yml ships search.js alongside data.js.

Verified by regenerating: 123 static pages, 123 unique titles and
descriptions with no page over 160 characters, a 123-entry search index, and
a 124-URL sitemap.

---------

Co-authored-by: MDA2AV <fabreis202@gmail.com>
@MDA2AV
MDA2AV deleted the nav-page-search branch July 24, 2026 21:55
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.

Re-add search functionality for pages

1 participant