Skip to content

fix(search): restore the API reference to search and stop docs-version renames from breaking it - #428

Open
eugenia-scandit wants to merge 4 commits into
mainfrom
fix/search-tag-ssot
Open

fix(search): restore the API reference to search and stop docs-version renames from breaking it#428
eugenia-scandit wants to merge 4 commits into
mainfrom
fix/search-tag-ssot

Conversation

@eugenia-scandit

Copy link
Copy Markdown
Collaborator

What was broken

Releasing 8.5.3 renamed the docs version, so docusaurus_tag on every page at
the site root changed from docs-default-current to docs-default-8.5.3
while not a single URL changed.

Two consequences, both silent:

  1. The API reference lives in the same index but is not a Docusaurus version, so
    it carried the tag docs-default-current. While that tag matched the guides'
    tag, it was found alongside them for free. After the rename ~3,200 pages left
    every result. A query with 106 matching pages in the index returned 86.
  2. buildVersionTagByMajor let current win its major unconditionally. With
    8.6.0-beta as current and 8.5.3 as lastVersion, typing "v8" sent readers
    at the unreleased beta's tag — and it still returned results, so nothing
    looked wrong.

The monitoring could only report "too few records".

What this changes

  • docusaurus.config.ts is the only place versions are declared and tags are
    built. DOCS_LAST_VERSION is declared once beside docsVersions (it used to
    be restated in the preset), and docVersionTag is the only constructor of
    docs-default-* strings.
  • buildVersionTagByMajor follows lastVersion and skips unreleased versions.
  • The API reference is mapped per version instead of bolted on: each docs
    version gets the API tree it belongs with — 7.6.14 → api-reference-7.6,
    6.28.11 → api-reference-6.28, and the version served at the root → the
    unversioned tree. A reader on 6.28.11 no longer gets 8.x API pages.
  • Fixes a regression introduced in this same PR: hoisting DOCS_LAST_VERSION
    left scripts/update-version.py reading the lastVersion: line, so the next
    release would have aborted with "Already in production state". Verified by
    running a real release end to end.

Why the mapping mirrors the site rather than assuming symmetry

The sitemap contains zero /data-capture-sdk/ URLs, so the crawler can only
reach that tree by following links. The 7.6.14 guides link to
/7.6/data-capture-sdk/…, but the guides served at the root link to the
unversioned /data-capture-sdk/… — nothing anywhere links to /8.5/.
Pointing the served version at api-reference-8.5 would have pointed at a tree
the crawler never reaches, dropping the current API reference out of search a
second time.

Preventing a repeat

  • yarn verify:search-tags (in CI) compares the build against the live index:
    the tag a typed major routes to must be the tag the site serves; the build must
    emit every tag the config names; and content under a tag search cannot reach is
    an error. Crawler lag warns instead of failing.
  • yarn test:search-facets (in CI) — 7 assertions on what the widget actually
    sends to Algolia, including that a legacy version gets its API reference and
    not the current one.

Both reproduce both bugs against the pre-fix config.

eugenia-scandit and others added 4 commits August 19, 2026 10:46
Releasing 8.5.3 renamed the docs version from `current` to `8.5.3`.
Docusaurus builds `docusaurus_tag` from the version NAME, so every page
at the site root flipped from `docs-default-current` to
`docs-default-8.5.3` without a single URL changing.

Two things broke, both silently:

1. The generated API reference under /data-capture-sdk/ is crawled into
   the same index but is not a Docusaurus version - it is tagged
   `docs-default-current`. While lastVersion was "current" it happened to
   share the guides' tag and rode along for free. After the rename it no
   longer matched the contextual filter, and ~3,200 pages left every
   search result. A representative query returned 86 hits where the index
   held 106 reachable ones.

2. buildVersionTagByMajor let `current` win its major unconditionally.
   With 8.6.0-beta as current and 8.5.3 as lastVersion, typing "v8"
   routed readers at the unreleased beta's tag - which still returned
   results, because that tag held the API reference, so nothing looked
   wrong.

Neither failed loudly. Search just got worse, and the monitoring could
only report "too few records".

Changes:
- docusaurus.config.ts is now the single source of truth for versions and
  every tag derived from them. DOCS_LAST_VERSION is declared once beside
  docsVersions instead of being restated in the preset, docVersionTag is
  the only place a `docs-default-*` string is built, and
  ALWAYS_ON_SEARCH_TAGS names the indexed content Docusaurus cannot tag
  for us.
- buildVersionTagByMajor now follows lastVersion and skips unreleased
  versions, so a typed major routes where the reader actually is.
- SearchBar widens the contextual OR group with the always-on tags, and
  the typed-version rewrite no longer clobbers them.
- A build plugin writes build/search-tags.json, and
  scripts/verify-search-tags.cjs (yarn verify:search-tags, wired into
  CI) checks it three ways: the routed tag for the served major must be
  the served tag, the build must actually emit every tag the config
  names, and no tag holding real content may sit outside what search can
  reach. Crawl lag warns; config drift fails.

The gate reproduces both bugs on the pre-fix config and passes on this
one. It also surfaces two orphan cohorts left by earlier renames -
docs-default-8.0.0 (10 pages) and docs-default-6.28.1 (18) - which want
purging from the index.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
My previous commit restored the API reference to search by OR-ing its tag
in on every page - including the frozen 7.6.14 and 6.28.11 trees, where it
had never appeared before. Measured on a 7.6.14 page, one query went from
53 hits to 73, and all 20 extras were current-SDK API pages that do not
apply to a reader on that version.

Before the 8.5.3 rename this scoping happened by accident: the API
reference shared the served version's tag, so it appeared there and
nowhere else. This makes it explicit - alwaysOnScopeTags names the
versions the extra tags apply to (the served version and the
in-development one), and the widget injects them only when the page's own
tag is in that set.

Also starts the crawler migration. The API reference should not be tagged
with a version name at all: `docs-default-current` is the 8.6.0 beta's own
tag, which is exactly why a release could rename the API reference out of
search. ALWAYS_ON_SEARCH_TAGS now lists `api-reference` alongside it, so
retagging the Algolia crawler's /data-capture-sdk/** action can land
before or after this commit without breaking search either way. The gate
reports an empty always-on tag as a pending migration, and only fails if
no always-on tag carries the content.

Adds scripts/test-search-facets.cjs (yarn test:search-facets, wired into
CI). It reads the two functions out of the shipped module rather than
copying them, and pins both failure modes: too narrow and content vanishes
from search, too wide and legacy readers get results that do not apply.
Neither throws in production, so only an assertion catches them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
I had this wrong twice, and the correction matters: the API reference IS
versioned. It is published per major.minor line at
/<major.minor>/data-capture-sdk/<framework>/ - /6.28/, /7.6/, /8.4/, /8.5/,
/8.6/ all return 200. My earlier probes used /6.28.11/, which 404s, and I
concluded from that there was only one API reference. There is one per line,
and each docs version has a matching one.

That makes the previous design wrong in both directions: OR-ing one API
reference into every version polluted legacy search with current-SDK pages,
and scoping it to the served version alone hid the 6.28 and 7.6 API
references from the readers they belong to.

So the API reference is now mapped per version rather than bolted on.
buildApiReferenceTags derives, from docsVersions alone, the tag each docs
version's API reference carries: docs-default-6.28.11 -> api-reference-6.28,
docs-default-7.6.14 -> api-reference-7.6, docs-default-8.5.3 ->
api-reference-8.5, docs-default-current -> api-reference-8.6. A reader on
6.28.11 gets the 6.28 API reference and never the 8.x one, and typing "v7"
moves the guides and the API reference together.

Nothing here needs maintaining per release. The repo reads the line out of
docsVersions; the crawler is expected to read it out of the URL
(/8.5/data-capture-sdk/... -> api-reference-8.5). Neither side hard-codes a
version, which is the whole point: tagging the API reference with a docs
version NAME is what broke search when 8.5.3 renamed it.

Also fixes a regression I introduced. Hoisting DOCS_LAST_VERSION left
scripts/update-version.py reading the `lastVersion:` line, whose last quoted
string is now "current" - so the next release would have aborted with
"Already in production state". All four read/write sites now target the
constant, which is the value both the docs plugin and the tag derivation
actually use.

Tests rewritten around the version mapping: a legacy version gets ITS API
reference and not the current one, an unknown version adds nothing rather
than guessing, and a typed version moves both together. 7 passing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…links

Correcting my own previous commit. It mapped the served version to
`api-reference-8.5`, on the assumption that every docs version has a
matching /<major.minor>/data-capture-sdk/ tree the crawler can reach. It
does not, and the assumption would have dropped the current API reference
out of search a second time.

What the site really does, verified against production:

  - the sitemap contains ZERO /data-capture-sdk/ URLs, so the crawler can
    only find that tree by following links
  - the 7.6.14 guides link to /7.6/data-capture-sdk/...
  - the guides served at the root link to the UNVERSIONED
    /data-capture-sdk/... - nothing anywhere links to /8.5/

So /8.5/data-capture-sdk/ exists but is undiscoverable, and pointing the
served version at it would have pointed at an empty tag.

The mapping now mirrors the site's own linking instead of assuming a
symmetry that isn't there: the version served at the root and the
in-development one take the unversioned tree (`api-reference-latest`),
every frozen version takes its own line (`api-reference-7.6`,
`api-reference-6.28`). That is what the crawler will actually produce from
the URL, and it stays automatic - this file reads the version out of
docsVersions, the crawler out of the URL, neither hard-codes one.

Records are only added by this change, never removed: the unversioned tree
keeps its URLs and just changes tag. maxLostRecordsPercentage does not need
raising.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1

🚀 View preview at
https://Scandit.github.io/data-capture-documentation/pr-preview/pr-428/

Built to branch gh-pages at 2026-08-20 16:12 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

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