Skip to content

Publish a current API reference per SA target with visible history - #95

Merged
davidalucas merged 9 commits into
mainfrom
94-api-reference-current-per-target
Oct 6, 2026
Merged

davidalucas merged 9 commits into
mainfrom
94-api-reference-current-per-target

Conversation

@davidalucas

@davidalucas davidalucas commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The API reference now grows with current content plus a deduplicated history, not with every release × SA target. This implements option A of #94, with one refinement from maintainer review: readers building for an earlier SpatialAnalyzer must find their version as easily as the latest one.

  • A current reference per SA target. /api/<family>/sa-<target>/… shows the newest Briosa release that documents that target, at an address that stays the same across releases. If a future release drops SA 2024, SA 2024 readers keep a complete reference at the same URL.
  • An SA chooser for each API family. /api/<family> is now an indexable page that asks which SpatialAnalyzer version you build for, and lists earlier releases. Previously it was a client redirect.
  • A SpatialAnalyzer Compatibility table at the top of every method page. It shows, for each target, whether the method is documented, the current release, and the first release that documented it. It links to the method's release history.
  • First-class history pages. /api/<family>/<group>/<method> shows each distinct published contract once: signature, tables, and examples, the release/SA pairs that published it, and field-level changes from the previous revision. Each pair links to its own release's group notes and released source; group notes differ between almost every release, so they are linked, not shared. Each pair has a stable anchor, such as #release-0.7.0-sa-2024.1.0508.5. History pages are indexed, listed in the sitemap, and get their own search records. They no longer auto-redirect to a remembered target. While a pair is being read, its release and target stay in the selectors, the eyebrow, and the address (?release=&sa=) through section links. The history sidebar moves between method histories, keeping the pair, and the group breadcrumb links that pair's group notes.
  • Earlier releases keep their guides, group notes, and first-call walkthroughs at /api/<family>/sa-<target>/<release>/ (noindex). Their method links open the matching history revision.
  • Former addresses become static redirect documents, not client routes. That covers 30,646 documents: release-qualified method URLs, pre-Redesign API navigation with persistent SA context and method pages #76 group URLs, and first-call aliases. Each has noindex, a canonical link, and no-JavaScript fallback links. One shared script, /assets/api-redirect.js, handles fragments, method anchors, and a remembered SA target. A section of an earlier release's method page goes to where its content is kept: the revision's own headings and parameter rows, the history availability table for Version Differences, the release's group notes for Execution Notes, and the release's guide for a first-call walkthrough. Anything else lands on the release/SA pair, never on an anchor that does not exist. The release-first method aliases from Redesign API navigation with persistent SA context and method pages #76's pre-merge branch were never canonical and are retired. The set is frozen: only releases listed in targets.json compatibilityAddresses, those whose release-qualified addresses were actually published, get redirect documents, so new releases add none. A fixture test checks this. In the same fixture, unversioned pre-redesign group addresses and their #method anchors resolve against the current reference, not the frozen release.
  • Site links rewritten. 2,657 catalog, guide, homepage, and redirect-config links that pointed at former addresses now point straight at canonical pages, so the broken-link check still covers them.

Measurements

Before (main 62135ae) After
API routes 66,411 14,443
Static redirect documents 0 30,646
Peak Node working set (2 workers) 18.17 GB 10.39 GB
Build time 10.0 min 5.2 min
main.js (every page) 29.8 MB / 2.39 MB gzipped 6.2 MB / 0.67 MB gzipped
Files / size 70,801 / 1.8 GB 47,702 / 0.76 GB

Local Windows measurements, summing the working set of the build's Node processes. On Docs CI (ubuntu-latest, 16 GB), total runner memory in use, including the OS, peaked at about 11.5–11.8 GB across this PR's runs, and the build step took about 4.3 minutes. Total runner memory does not isolate the build, so it does not verify #94's 10 GB build-memory criterion. Both build workflows now also report the peak resident memory of the build's own Node processes in the job summary, and warn when it exceeds 10 GB. On ca39ed4 the build's Node processes peaked at 10,163 MiB of the 10,240 MiB (10 GiB) budget, so the criterion is met with 77 MiB (under 1%) to spare. Runner memory in use peaked at 11,754 MiB of 15,989 MiB. The figure is sampled once a second and includes the small npm wrapper processes. With so little margin, the next release's growth will likely cross the budget unless memory is reduced first; a slimmer Version Differences table on current pages is the next lever. (An earlier attempt, on c956706, matched no process named node and recorded nothing; ca39ed4 matches the Node executable in the command line, and a missing measurement can no longer fail the build.)

Size Budgets (Revised in #94)

#94's original size budgets were 300 MB excluding redirect documents, 2 KB per redirect document, and "a few hundred files" per release. This PR does not meet them. That was an oversight, not a decided trade-off: I set those budgets before measuring any build, and did not check the build against them until review. At the maintainer's request, #94's criteria now use measured values (comment), and size reduction is deferred.

  • Excluding redirect documents: 17,028 files, 719 MB (revised budget: 20,000 files, 800 MB).
    • HTML: API page HTML is about 583 MB, about 40 KB a page across 14,439 pages. About 27 KB of each is repeated chrome: sidebar about 15 KB, footer 5 KB, navbar 4 KB, head 3 KB.
    • Client data: page data for client navigation adds about 117 MB.
    • Whole site: 0.76 GB, down from 1.8 GB and under GitHub Pages' 1 GB limit.
  • Redirect documents: 44 MB (revised budget: 50 MB). All 29,140 without method anchors are under 2 KiB. The 1,081 former group addresses carry one no-JavaScript link per method anchor, as Redesign API navigation and publish version-aware MP method pages #75 requires; the largest is about 62 KiB (revised budget: 80 KiB).
  • Growth: a release of every family adds no redirect documents. It adds about 512 pages (64 per superseded release/SA context), roughly 1,000 files and 30 MB. The 800 MB budget therefore allows about two release cycles.
  • Later options: rendering API sidebars only in the browser (about 200 MB), or sharing one page between SA targets whose contracts are identical.

Revisions to #75

As proposed in #94: individual static pages exist for each method in the current release of each documented SA target. Older release/SA combinations are revisions on the history page, reachable from their former URLs. Every URL that was ever canonical or linked by the site still resolves to static HTML. AGENTS.md, README.md, and the contributing guide describe the new model.

Search

search/algolia-crawler.cjs now emits one record per history revision, faceted by every release and SA target that published it. The hosted crawler configuration has to be updated and recrawled after deployment. That is not done here.

Verification

  • npm ci and npm run check on Node.js 24 pass locally: typecheck, production build with no broken-link or broken-anchor warnings, 9 search tests, and 24 SEO, release, and API tests.
  • History change summaries report field renames (for example Renamed angle_tolerance_0_0_for_none → angle_tolerance). They claim matching parameter tables only when both revisions have parsed tables, and a regression test covers this.
  • History selectors keep the SA target being read. Going from SA 2024 Direct CAD Access to Server 0.7.0 and then 0.8.0 stays on the SA 2024 contract, where surface_compatibility_mode is required. A missing pair is reported, never replaced. Section bookmarks on release-qualified addresses carry their pair as ?release=&sa=, so after …/sa-2024.1.0508.5/0.7.0/…#request-parameters, changing only the SA target lands on Server 0.7.0 for SA 2026. A test runs the built redirect script. Following a section permalink while reading Server 0.7.0 / SA 2024, then changing only the SA target, stays on Server 0.7.0. Moving to another method's history through the sidebar keeps the pair. A test also follows every former method address of one earlier release for each kind of section and checks that the destination anchor exists.
  • The address decides which history pair is shown. A pair anchor removes a conflicting query, and a section anchor keeps a query pair only when that pair published the revision. The page corrects its address whenever it disagrees with the selectors. Choosing 0.8.0 / SA 2026 in the availability table and then that revision's permalink keeps 0.8.0 / SA 2026.
  • Links and redirects for a pair that never documented a method name that pair, for example ?release=0.7.0&sa=2026.1.0529.7 for Run Crib Sheet. The history page reports the gap instead of reopening a pair remembered from earlier reading. Canonical links of redirect documents omit the query.
  • A requested pair is the pair carried to the next history page, even when the page reports it unavailable. Reading 0.7.0 / SA 2024, then opening the former 0.7.0 / SA 2026 Run Crib Sheet address, then Direct CAD Access from the history sidebar shows 0.7.0 / SA 2026. It does not revert to SA 2024. A test follows that sequence.
  • The remembered pair is scoped to its API family. Reading gRPC Server 0.7.0 / SA 2026 and then a Python history page carries only the SA target, never a gRPC release number. A test covers that transition.
  • Search derives the current release for release-independent addresses from plugin data (api_release:0.9.0), not from a URL segment.
  • Checked in the browser: the family SA chooser, current and unavailable method pages, a history page, an earlier-release group page, and a redirect from an old 0.7.0 SA 2024 method URL with #request-parameters. That redirect landed on the matching history revision's request table. No console errors, and no horizontal scroll at phone width.
  • Not done here: hosted deployment, the hosted crawler update and recrawl, and search-console checks. Merging deploys to briosa.dev.

Refs #94, #93, #75

🤖 Generated with Claude Code

davidalucas and others added 5 commits October 4, 2026 14:19
Render each SpatialAnalyzer target at the newest Briosa release that
documents it, at a release-independent address, so readers building for
an earlier SA keep a complete reference that does not move. Each API
family now starts with an indexable SA chooser, and every method page
opens with a SpatialAnalyzer Compatibility table linking to its release
history.

Method history pages show each distinct published contract once, with
the release/SA pairs that published it, per-pair anchors, links to each
release's own group notes and released source, and field-level changes
from the previous revision. They are indexed and searchable. Earlier
releases keep their guides and group notes at release addresses.

Former addresses (release-qualified methods, pre-redesign group URLs,
and first-call aliases) become static redirect documents written after
the build instead of client routes. They keep noindex, canonical links,
no-JavaScript fallbacks, fragment and method-anchor mapping, and the
remembered SA target. Release-first method aliases, which were never
canonical, are retired. Site links that pointed at former addresses now
point directly at canonical pages.

This cuts the API from 66,411 routes to 14,413, peak local build memory
from 18.2 GB to about 10.4 GB, build time from 10 to about 5 minutes, and
the site-wide main.js from 2.39 MB to 0.67 MB gzipped. Both build
workflows now report peak runner memory.

Refs #94, #93

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A revision that renamed a field was described as having matching
parameter tables. Report renames alongside type and default changes,
and claim matching tables only when both revisions have parsed tables.

Refs #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a method history page, changing the release took the first
documented pair for that release, silently switching SA targets (for
example from the SA 2024 Direct CAD Access contract, where
surface_compatibility_mode is required, to SA 2026's). History pages
now track the pair being read from its anchor, or the reader's SA
target, keep it across release changes, keep the release across target
changes, and report a missing pair instead of substituting another.
Release-qualified redirect documents record their SA target for this.

Redirect documents were generated for every loaded release, so each
new release would have added thousands. They are now limited to the
releases whose release-qualified and pre-redesign addresses were
published, recorded in targets.json compatibilityAddresses, with
pre-redesign routes resolved against the newest of those releases. A
fixture test confirms a new release adds none.

Search derived api_release from a URL segment that current references
no longer have. The plugin now publishes each target's current
release, and the search bar uses it for release-independent addresses.

Refs #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A section bookmark on a release-qualified method address (for example
SA 2024 / Server 0.7.0 Direct CAD Access #request-parameters) reached
the right history table but kept only the SA target, so changing the
target then jumped to the current release. Section redirects now carry
the pair as ?release=&sa=, and history pages read a documented pair
from the anchor or that query before falling back to the reader's
target. A test runs the built redirect script and the selector logic.

Unversioned pre-redesign group addresses led to the current group page,
but their #method anchors still resolved against the frozen release, so
after a new release they pinned readers to its history. Their anchors,
including any published only by the frozen release, now resolve against
the current reference. Release-qualified addresses stay pinned. The
release-upgrade fixture test covers both targets.

Refs #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Selecting Server 0.7.0 / SA 2024 on a method history page and then
following a section permalink dropped the release, so a target change
opened Server 0.9.0. History pages now keep the pair being read in the
tab and in the address: a section link keeps it (or, arriving cold,
selects that revision's newest pair for the reader's target), and the
page writes ?release=&sa= so reloads and shared links retain it.

History pages also bound their sidebar and group breadcrumb to the
newest target's current reference. Their sidebar now moves between
method histories, which keep the pair, and the group breadcrumb links
the group notes of the pair being read and names it.

Redirects from earlier releases' method pages prefixed any fragment,
manufacturing anchors such as #revision-2-version-differences. They now
map each former section to its retained content: contract headings the
revision has, parameter rows only where it has tables, Version
Differences to the history availability table, Execution Notes to the
release's group notes, and a first-call walkthrough to the release's
guide page, which earlier releases keep again. Anything else lands on
the release/SA pair. The logic lives in one shared script, which also
shrinks every redirect document; a test follows every former method
address of one earlier release for each kind of section.

Refs #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
davidalucas and others added 4 commits October 4, 2026 21:37
A query pair outlived in-page navigation: after choosing 0.8.0 / SA 2026
in the availability table, a revision permalink restored the stale
0.7.0 / SA 2024 query, so the toolbar and breadcrumb disagreed with the
section shown. A pair anchor now decides and removes a conflicting
query; a section anchor keeps a query pair only when that pair
published the revision; and the page corrects its address whenever it
disagrees with the selectors.

Addresses for a pair that never documented a method (for example the
former 0.7.0 / SA 2026 Run Crib Sheet URL) led to its history page
without naming the pair, so a pair remembered from earlier reading
reopened another target's contract. Those links and redirects now name
the requested pair, and the history page reports that it is not
documented instead of consulting memory. Canonical links of redirect
documents omit the query.

Refs #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reading 0.7.0 / SA 2024, then opening the former 0.7.0 / SA 2026 Run
Crib Sheet address (correctly reported unavailable), then moving to
Direct CAD Access in the history sidebar reverted to SA 2024: the
unavailable request updated the remembered target but left the older
pair stored. A requested pair is now the pair the tab carries forward
whether or not the page documents it, and a page that does not
document the carried pair reports it rather than substituting another.
A test follows that sequence.

The build workflows reported only total runner memory. They now also
sample the resident memory of the build's Node processes, report it
against the 10 GB budget in #94, and warn when it is exceeded.

Refs #94, #93

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sampler selected processes with `ps -C node`, which matched nothing
on the runner, so no build figure was recorded and reading it failed the
Build site step after a successful build. Match the node executable in
each process's command line instead, and never let a missing
measurement fail the build: report it as unmeasured with a warning.

Refs #94, #93

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tab's remembered release/SA pair used one storage key for every API
family, so after reading gRPC Server 0.7.0 / SA 2026, the Python
history of the same method added ?release=0.7.0 and reported "Client
0.7.0 does not document this method", although Python's releases are
0.1.0 to 0.4.0. The pair is now stored with its family and read only by
that family's history pages. The SA target still carries across
families. A pair stored without a family is ignored. A test follows
the gRPC-to-Python transition.

Refs #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@davidalucas
davidalucas merged commit 216c875 into main Oct 6, 2026
1 check passed
@davidalucas
davidalucas deleted the 94-api-reference-current-per-target branch October 6, 2026 22:42
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