docs: SEO/GEO audit fixes, comparison pages, and broken doc validation repair - #978
Draft
samber wants to merge 15 commits into
Draft
docs: SEO/GEO audit fixes, comparison pages, and broken doc validation repair#978samber wants to merge 15 commits into
samber wants to merge 15 commits into
Conversation
…CI validation The docs/data/*.md frontmatter parser used by every check-*.js validation script only understood single-line YAML arrays, so it silently returned an empty list for every similarHelpers/variantHelpers field (all of them use multi-line lists). Every cross-reference check has therefore been a no-op since it was written, and the CI job that runs them was itself commented out in .github/workflows/doc.yml. - Replace the hand-rolled frontmatter parser with gray-matter, matching what the Docusaurus plugin itself already uses - Fix check-helpers-visible-in-pages.js, which only recognized categories core/mutable/parallel and crashed on iter/experimental -- this is why 11 documented iter/math and iter/condition helpers had no rendering page at all (404 in production) - Fix check-filename-matches-frontmatter.js's category-to-file-prefix mapping (iter -> it-, experimental -> simd-), which produced 166 false-positive mismatches and made the check unusable - Add check-duplicate-slugs.js and wire everything into a single check-docs script, then re-enable the CI job that runs it - Auto-fix 273 broken similarHelpers/variantHelpers references (wrong subcategory, or pointing at a variant collapsed into a parent card) and remove 43 references to helpers that don't exist anywhere in the documented corpus - Fix 2 duplicate slugs (core-isnotnil, it-channelseq) that produced colliding HTML ids on the same page - Add docs/docs/iter/math.md and docs/docs/iter/condition.md so the 11 orphaned helpers are actually reachable - Add generated-index links to the 5 top-level sidebar categories, which gives the "it" package (157 helpers, previously reachable only via in-category links) inbound links from every other category
…d guide iter.Range(0, 1000) does not exist in the standard library (only Seq, Seq2, Pull, Pull2), lom.Filter was called with a pointer against a signature that takes the slice by value and returns the result, and lop.Map was called with a worker-count argument the function does not take. All three examples now match the real signatures in it/math.go, mutable/slice.go and parallel/slice.go.
…eadiness page The site had zero evaluation content: nothing to intercept "do I still need lo now that Go has slices/maps", "is lo still maintained", or "how do I migrate off go-funk". These are the queries where third-party mirrors currently get cited instead of the site itself. - /compare/samber-lo-vs-go-stdlib: function-by-function overlap with slices/maps, including an explicit "when to use the standard library instead" section - /compare/samber-lo-alternatives: honest comparison with lancet, go-funk, go-linq and pie, with verified GitHub stats (stars, last push, last release) rather than assumptions - /compare/samber-lo-vs-go-funk: migration guide with a full function mapping table, verified against go doc github.com/thoas/go-funk - /compare/performance: real go test -benchmem results (not estimates) showing lo.Map's allocation profile is identical to a hand-written loop, and 4x lower than go-funk's reflection-based Map - /guides/lo-and-ro: a decision guide (not a "vs" page) between lo (finite, in-memory collections) and ro (infinite, event-driven streams), including a combined usage example - /guides/from-lodash: a Lodash-to-Go function equivalence table for developers coming from JavaScript/TypeScript - /production-ready: verified adoption (21,408 stars, 12,533 importers per pkg.go.dev), test coverage (96.1% per Codecov) and versioning policy, for reviewers evaluating the dependency FAQPage JSON-LD is included on the stdlib and go-funk comparison pages. All external facts (stars, releases, coverage) were checked against the GitHub API, pkg.go.dev and Codecov on 2026-08-20 rather than carried over from assumption.
The previous llms.txt was 745 lines of prose with 7 URLs total, only one of which pointed back into the site -- an agent reading it got function names with no way to navigate to their documentation. It also asserted a fabricated benchmark result (lo.Uniq shown as 5x slower than a manual loop) and three different, all-incorrect helper counts (300+, 500+, "hundreds"). llms.txt is now a short (6 KB) linked index generated from docs/data/*.md: one entry per documented page, with its real helper count and a same sample of helper names, plus links to the new comparison/guide pages. The previous prose content moves to the new llms-full.txt (277 KB), generated from the same source, for agents that want the complete corpus in one file. Both are referenced from robots.txt.
…ossary - Deduplicate titles/descriptions across the 27 helper category pages. Four pages shared the literal title "Slice" (core/iter/mutable/ parallel), with three more duplicated pairs (Map, Find, Channel, Intersect, String, Tuple, Type manipulation) -- none of them contained the word "Go". Every page now has a unique, keyword-bearing title and a 150+ character description naming its actual helpers. - Remove the ":::warning Help improve this documentation, still new and evolving" admonition that was duplicated verbatim at the top of all 27 pages -- it was the first extractable passage on every indexable page, ahead of the actual content. Replaced with each page's own description as an intro paragraph, and a short feedback link moved to the page footer. - Fix the homepage <title> (was 155 characters with the site name repeated twice, since Docusaurus appends it automatically on top of a manually duplicated one) and add a stats banner (helper count, stars, importers, license) plus a link to the new /production-ready page. - Rewrite /community with real numbers (contributors, stars, importers) instead of zero indexable content, and fix "Start contributing!" which linked out to a README anchor instead of /docs/contributing. - Expand the glossary from 13 sparse, unlinked entries to 30, each cross-linked to the helpers and pages that use the term (iter.Seq, type constraints, debounce/throttle, tuples, set operations...). - Add a global JSON-LD graph (Person, WebSite, SoftwareSourceCode) to docusaurus.config.ts headTags -- the homepage previously had no structured data at all. Also de-duplicate og:image/twitter:card/ twitter:image/og:locale (Docusaurus already emits these from themeConfig.image and i18n.defaultLocale; a second, hardcoded copy produced conflicting tags on every page), fix og:type to use the `property` attribute instead of `name` (Open Graph requires it and silently ignores the wrong one), and add an ecosystem footer column linking to ro/do/mo/oops/hot. - Correct the helper count (300+/500+/"hundreds", depending on the page) to the actual 449 in about.md. - Add a documentation link near the top of the README, before the single existing mention was ever reached.
Two gaps in the existing tracking: - Algolia search was only captured on Enter, but DocSearch is an as-you-type search -- most users never press it. Now also debounced on input, reading DocSearch's own result DOM to emit search_no_results (a direct, free signal of missing content, in the visitor's own words) or search_results with a hit count. - No signal existed for which of the 449 helpers people actually look at, on pages that list dozens of them. helper_viewed fires once per helper per page view via IntersectionObserver, after it has been at least half visible for 2 seconds, with its position on the page.
…ty hero image - Add docs/vercel.json to cache hashed assets and images for a year (they were previously served with a 4-hour max-age despite the filename hash making them immutable by construction). - Mark the sponsor logo link as rel="sponsored" per Google's guidance for paid placements. - Replace the /community hero image with a resized WebP: 6206x2224 source down to the 1200x430 it's actually displayed at, 893 KB down to 76 KB.
…kg.go.dev - AGENTS.md at the repo root: which of the four packages (lo, lo/it, lo/mutable, lo/parallel) to reach for, when the standard library is the better choice, and the naming/suffix conventions, aimed at coding agents editing this codebase or a consumer's. - doc.go: the module had no package-level doc comment, so pkg.go.dev and `go doc` had nothing to show beyond the README rendering.
Nothing in check-docs actually compiled the Go embedded in docs/data/*.md and docs/docs/**/*.md, so signature drift and copy-paste mistakes in examples went unnoticed indefinitely (getting-started.md shipped three non-compiling examples for a while). This wraps every fenced go block into a standalone program and builds it against the local source tree via a go.mod replace directive. Wired into check-docs and the validate-doc CI job, which now needs Go and goimports installed alongside Node.
docs/scripts/validate-go-code-blocks.js surfaced over 200 real compilation bugs across ~97 files: variable names reused across independent examples with incompatible types, missing type/helper declarations, generic constraint violations (Clonable, comparable, numeric-only), wrong argument types, and a few undefined cross-references between separate example blocks in the same file. Each fix keeps the original example's pedagogical intent and the file's existing style; no frontmatter or signatures were changed.
samber
commented
Aug 21, 2026
samber
left a comment
Owner
Author
There was a problem hiding this comment.
- Wired validate-go-code-blocks.js into check-docs, which now catches signature drift and copy-paste mistakes in every Go example before merge (getting-started.md shipped 3 non-compiling examples unnoticed until now).
- Fixed the ~200 real compilation bugs it found, in one grouped commit, keeping each example's original pedagogical intent.
| - name: Setup Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version-file: '../go.mod' |
Owner
Author
There was a problem hiding this comment.
go-version-file is resolved relative to GITHUB_WORKSPACE, not the docs/ working-directory default set below (that default only applies to run: steps, not uses: steps) — hence ../go.mod.
|
|
||
| # - name: Install dependencies | ||
| # run: npm i | ||
| - name: Install goimports |
Owner
Author
There was a problem hiding this comment.
validate-go-code-blocks.js shells out to goimports (per-block, so one bad snippet doesn't block import resolution for the rest), so CI needs it installed alongside Go.
Drops content unrelated to the original SEO/GEO audit that had crept into this branch: - docs/data/*.md: revert the mechanical Go-example fixes (keep only validate-go-code-blocks.js itself, unwired from check-docs for now) - doc.go: drop the package-level doc comment - docs/scripts/check-*.js: revert to their pre-fix versions - docs/static/img/*: restore the images removed as "unused" cleanup - docs/docusaurus.config.ts: drop rationale comments explaining why certain meta tags are intentionally absent
Drops every docs/data/*.md and docs/scripts/utils.js change made on this branch, including the earlier P0 cross-reference/frontmatter fixes -- out of scope for this PR going forward.
The "N helpers for..." sentence on each core/iter category page (and its meta description) hardcoded a number that silently drifts every time a helper is added or removed from that category. Added a HelperCount component that reads the count from the same helpers-pages plugin data HelperList already renders, and dropped the number from the static frontmatter description entirely (it can't run a component at build time).
lo-and-ro is a comparison between two libraries, not a how-to guide, so it belongs in compare/ alongside the other samber/lo comparisons rather than in its own guides/ section (now removed along with from-lodash, which had no other home). Updates every internal link that pointed at the old /guides/* paths, and drops the maturity/versioning table from the page (star counts and version numbers age too fast to maintain here).
Keeps only validate-go-code-blocks as an addition; every other check-* script entry and check-docs itself go back to their master definitions, out of scope for this PR going forward. Also restores the lo. prefix in about.md's Uniq example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to a deep SEO/GEO audit of the documentation site. Along the way, the
audit surfaced real bugs unrelated to search ranking (broken doc validation, an
entirely disabled CI job, 11 helpers with no rendering page, non-compiling
getting-started examples) — those are fixed here alongside the SEO/GEO work.
check-*.jsdoc validation script parsed frontmatter with a hand-rolledregex that silently returned empty arrays for multi-line YAML lists, so
cross-reference checks were a no-op; the CI job that ran them was also
commented out entirely. Both are fixed and re-enabled, which surfaced and
let this PR auto-fix 273 broken
similarHelpers/variantHelpersreferences, 2 duplicate slugs, and 11 orphaned
iterhelpers that had nopage at all (404 in production).
the real signatures.
/compare/*and/guides/*pages (stdlib comparison, alternatives,go-funk migration, verified benchmarks, lo-vs-ro decision guide, Lodash
equivalence table) and a
/production-readypage — all external facts(stars, releases, coverage) checked against the GitHub API, pkg.go.dev and
Codecov on 2026-08-20.
llms.txtas a linked index (was 745 lines of prose with afabricated benchmark and one working link) and added
llms-full.txt.removed a duplicated "still new and evolving" admonition that was the
first extractable passage on every page, expanded the glossary, and added
structured data (
Person/WebSite/SoftwareSourceCode,FAQPage).AGENTS.mdand a packagedoc.go.Each commit is scoped to one concern — see individual commit messages for the
full detail and reasoning.
Test plan
Verified locally before opening this PR:
cd docs && npm run build(passes withonBrokenLinks: 'throw'),cd docs && npm run check-docs(all cross-reference,duplicate-slug and orphaned-page checks pass), and
go build ./.... The new/compare/*,/guides/*and/production-readypages were also spot-checkedby serving the production build locally.