From 698e230b53408b8900787b0f7db2c164196fa5c3 Mon Sep 17 00:00:00 2001 From: PiotrWodecki Date: Mon, 27 Jul 2026 11:21:58 +0200 Subject: [PATCH 1/4] Fix docs search ranking and index staleness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two unrelated-looking problems with the same root: search results were ranked almost entirely by heading depth, and the index lagged releases. Rank guides above generated API reference ----------------------------------------- The Algolia index ranks on desc(weight.pageRank) first, but the crawler never set pageRank, so all 16.5k records sat at 0 and the criterion was inert. API reference is ~70% of the index, so it buried hand-written guides on common queries. The crawler config now assigns pageRank as "version band + section weight" (latest release > older > unreleased; tutorials > how-to > explanation > api). That alone was not enough: the index sets exactOnSingleWordQuery to "attribute", so for a one-word query only a hit matching the *whole* attribute counts as exact. A generated heading that is literally "token" qualified; the "Security & Token Model" page did not. Algolia resolves `exact` before `custom`, so pageRank never got a say. Setting it to "word" at query time lets pageRank decide. It is set here rather than in the index settings because free DocSearch grants no editSettings key. Verified against the live index — searching "token" now returns the security concepts page, "agent" the agents tutorial, "peer" the list-other-peers guide. Exact API symbol lookup is unaffected. Reindex on release ------------------ Docusaurus contextual search filters on the current version's docusaurus_tag. A new version therefore has zero records until the crawler runs, and the search box returns nothing at all. 0.29.0 shipped on 23 Jul against a monthly crawl last run on 17 Jul, so docs search was dead for four days. The crawler is now on a weekly schedule, and this adds a job that triggers a reindex when versions.json changes. Requires ALGOLIA_CRAWLER_USER_ID and ALGOLIA_CRAWLER_API_KEY secrets. --- .github/workflows/docs.yaml | 27 +++++++++++++++++++++++++++ docusaurus.config.ts | 11 +++++++++++ 2 files changed, 38 insertions(+) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 53a60a2b..20ea4b37 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -59,3 +59,30 @@ jobs: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 + + # A new docs version creates a new docusaurus_tag in Algolia. Until the + # crawler indexes it, contextual search filters on a tag with zero records + # and the search box returns nothing, so a release must trigger a recrawl. + # Everything else is covered by the crawler's weekly schedule. + reindex: + needs: deploy + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + - name: Detect docs release + id: rel + run: | + if git diff --name-only HEAD^ HEAD | grep -qx 'versions.json'; then + echo "released=true" >> "$GITHUB_OUTPUT" + else + echo "released=false" >> "$GITHUB_OUTPUT" + fi + - name: Trigger Algolia crawler reindex + if: steps.rel.outputs.released == 'true' + run: | + curl -sS -f -X POST \ + -u "${{ secrets.ALGOLIA_CRAWLER_USER_ID }}:${{ secrets.ALGOLIA_CRAWLER_API_KEY }}" \ + "https://crawler.algolia.com/api/1/crawlers/9bc2ab68-0ce9-4f44-9824-3a48219680b2/reindex" diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 45a5e05e..39f3fb2d 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -310,6 +310,17 @@ const config: Config = { indexName: "Fishjam", contextualSearch: true, searchPagePath: "search", + searchParameters: { + // For single-word queries, treat an exact match on a whole *word* as + // exact, not only a match on the whole attribute. The index default + // ("attribute") means a generated API heading that is literally the + // query — e.g. an interface field named "token" — counts as exact, + // while the "Security & Token Model" concept page does not. Algolia + // decides `exact` before `custom`, so weight.pageRank never gets a + // say and reference pages bury the guides. Set here rather than in + // the index settings because free DocSearch grants no editSettings key. + exactOnSingleWordQuery: "word", + }, insights: false, askAi: { assistantId: "49fdf088-e614-4b89-86c2-da8c4b566260", From 54ae052be784ab0c967b3e80d640cdf78e385543 Mon Sep 17 00:00:00 2001 From: PiotrWodecki Date: Mon, 27 Jul 2026 11:29:31 +0200 Subject: [PATCH 2/4] Address review: widen release detection, drop job permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diffing HEAD^..HEAD only inspects the tip commit, so a push carrying several commits missed a release whose versions.json change was not last — reproduced against real history. Diff the full pushed range via github.event.before instead, falling back to the tip when it is absent (workflow_dispatch) or unresolvable (first push to a branch). This needs full history, since `before` can point anywhere. Also drop the reindex job to contents:read. It inherited pages:write and id-token:write from the workflow, which it never uses. --- .github/workflows/docs.yaml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 20ea4b37..a3e5d4d0 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -67,15 +67,32 @@ jobs: reindex: needs: deploy runs-on: ubuntu-latest + # Only needs to read the repo to diff and call an external API. + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@v4 with: - fetch-depth: 2 + # github.event.before can point anywhere in history, so a shallow + # clone is not enough to diff against it. + fetch-depth: 0 - name: Detect docs release id: rel + env: + BEFORE: ${{ github.event.before }} run: | - if git diff --name-only HEAD^ HEAD | grep -qx 'versions.json'; then + # Diff the whole pushed range, not just the tip: a push can carry + # several commits and versions.json may not be in the last one. + # workflow_dispatch has no `before`, and it is all-zeroes for a + # branch's first push, so fall back to the tip commit. + if [ -n "$BEFORE" ] && git cat-file -e "$BEFORE^{commit}" 2>/dev/null; then + base="$BEFORE" + else + base="HEAD^" + fi + echo "Comparing $base..HEAD" + if git diff --name-only "$base" HEAD | grep -qx 'versions.json'; then echo "released=true" >> "$GITHUB_OUTPUT" else echo "released=false" >> "$GITHUB_OUTPUT" From 19ecaaf1745d39d96a176727c17eb2972a58dc99 Mon Sep 17 00:00:00 2001 From: PiotrWodecki Date: Mon, 27 Jul 2026 11:37:20 +0200 Subject: [PATCH 3/4] Simplify release detection Gating the job on push events guarantees github.event.before exists, which removes the fallback branch, the cat-file probe and the env var. Folding the check into the curl step as an early exit removes the GITHUB_OUTPUT plumbing and the second step's condition. --- .github/workflows/docs.yaml | 38 +++++++------------------------------ docusaurus.config.ts | 10 ++-------- 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index a3e5d4d0..3d61a003 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -60,46 +60,22 @@ jobs: id: deployment uses: actions/deploy-pages@v4 - # A new docs version creates a new docusaurus_tag in Algolia. Until the - # crawler indexes it, contextual search filters on a tag with zero records - # and the search box returns nothing, so a release must trigger a recrawl. - # Everything else is covered by the crawler's weekly schedule. + # A new docs version starts with zero records in Algolia, and contextual + # search filters on it, so the search box returns nothing until a recrawl. reindex: needs: deploy + if: github.event_name == 'push' runs-on: ubuntu-latest - # Only needs to read the repo to diff and call an external API. permissions: contents: read steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 with: - # github.event.before can point anywhere in history, so a shallow - # clone is not enough to diff against it. fetch-depth: 0 - - name: Detect docs release - id: rel - env: - BEFORE: ${{ github.event.before }} - run: | - # Diff the whole pushed range, not just the tip: a push can carry - # several commits and versions.json may not be in the last one. - # workflow_dispatch has no `before`, and it is all-zeroes for a - # branch's first push, so fall back to the tip commit. - if [ -n "$BEFORE" ] && git cat-file -e "$BEFORE^{commit}" 2>/dev/null; then - base="$BEFORE" - else - base="HEAD^" - fi - echo "Comparing $base..HEAD" - if git diff --name-only "$base" HEAD | grep -qx 'versions.json'; then - echo "released=true" >> "$GITHUB_OUTPUT" - else - echo "released=false" >> "$GITHUB_OUTPUT" - fi - - name: Trigger Algolia crawler reindex - if: steps.rel.outputs.released == 'true' + - name: Reindex Algolia when a docs version is released run: | + git diff --name-only ${{ github.event.before }} ${{ github.sha }} \ + | grep -qx versions.json || exit 0 curl -sS -f -X POST \ -u "${{ secrets.ALGOLIA_CRAWLER_USER_ID }}:${{ secrets.ALGOLIA_CRAWLER_API_KEY }}" \ "https://crawler.algolia.com/api/1/crawlers/9bc2ab68-0ce9-4f44-9824-3a48219680b2/reindex" diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 39f3fb2d..cf709720 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -311,14 +311,8 @@ const config: Config = { contextualSearch: true, searchPagePath: "search", searchParameters: { - // For single-word queries, treat an exact match on a whole *word* as - // exact, not only a match on the whole attribute. The index default - // ("attribute") means a generated API heading that is literally the - // query — e.g. an interface field named "token" — counts as exact, - // while the "Security & Token Model" concept page does not. Algolia - // decides `exact` before `custom`, so weight.pageRank never gets a - // say and reference pages bury the guides. Set here rather than in - // the index settings because free DocSearch grants no editSettings key. + // Without this, generated API headings that are exactly the query + // outrank guides before weight.pageRank is ever consulted. exactOnSingleWordQuery: "word", }, insights: false, From 7029ece81aca280ba539557c1aed14d3f64201c5 Mon Sep 17 00:00:00 2001 From: PiotrWodecki Date: Mon, 27 Jul 2026 11:41:04 +0200 Subject: [PATCH 4/4] Match versions.json as a fixed string Unanchored, the dot is a regex wildcard, so versionsXjson would also match. No such path exists, but -F makes the exact-path check explicit. --- .github/workflows/docs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 3d61a003..2420ff44 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -75,7 +75,7 @@ jobs: - name: Reindex Algolia when a docs version is released run: | git diff --name-only ${{ github.event.before }} ${{ github.sha }} \ - | grep -qx versions.json || exit 0 + | grep -qxF versions.json || exit 0 curl -sS -f -X POST \ -u "${{ secrets.ALGOLIA_CRAWLER_USER_ID }}:${{ secrets.ALGOLIA_CRAWLER_API_KEY }}" \ "https://crawler.algolia.com/api/1/crawlers/9bc2ab68-0ce9-4f44-9824-3a48219680b2/reindex"