fix(seo): library-specific meta descriptions on implementation pages - #11203
Conversation
The SEO proxy reused the spec description verbatim as the meta/OG
description of every implementation page, so up to 15 library pages and
their hub carried an identical snippet — 4,254 plot pages had about 334
distinct descriptions, which Bing Webmaster Tools flagged. The snippet now
opens with "{title} in {library} ({language}): " before the description,
trimmed to 155 characters as before. Hub, body copy and JSON-LD unchanged.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu
There was a problem hiding this comment.
🟢 Approval recommended
The production change is localized and consistent with existing escaping/trimming behavior, and it includes test + documentation + changelog updates (only minor test robustness nits noted).
Pull request overview
This PR updates the SEO bot-page renderer so implementation pages use library-specific meta/OG descriptions (reducing duplicate snippets across the 15-per-spec implementation pages), while keeping the spec hub description unchanged.
Changes:
- Build implementation-page
<meta name="description">/og:descriptionas{title} in {library} ({language}): {spec description}, still trimmed to 155 characters. - Add a unit test asserting different libraries for the same spec produce different meta descriptions.
- Document the meta description rule in
docs/reference/seo.mdand add a changelog entry.
File summaries
| File | Description |
|---|---|
api/routers/seo.py |
Prefixes implementation-page meta/OG descriptions with title + library + language to make snippets unique per implementation page. |
tests/unit/api/test_seo_helpers.py |
Adds a unit test covering the new library-specific meta description behavior. |
docs/reference/seo.md |
Documents the meta description trimming and the implementation-page prefix rule. |
CHANGELOG.md |
Records the SEO fix under [Unreleased]. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Review feedback: guard re.search() before .group() and check the escaped <p>…</p> body instead of a substring that JSON-LD also carries. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu
There was a problem hiding this comment.
🔵 Needs a closer look
The new [Unreleased] changelog bullet is missing the required PR reference suffix (e.g. “(#NNNN)”).
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
CHANGELOG.md:35
- This new changelog entry is missing the PR reference suffix (e.g. "(#11199)") that the changelog header requires for every bullet under [Unreleased]. Please append this PR's number to the end of the bullet for consistency and traceability.
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped, matches the PR description, includes a focused regression test, and updates both documentation and the changelog.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0 new
- Review effort level: Lite
Summary
<meta name="description">/og:descriptionon every implementation page, so the up to 15 library pages of a spec and its hub shared one snippet. A 43-page sample as Bingbot had 32 distinct descriptions; catalogue-wide, 4,254 plot pages carry about 334._build_impl_htmlnow builds the snippet as{title} in {library} ({language}): {spec description}before the existing 155-character trim, so every page is unique and a searcher who typed "matplotlib funnel chart" sees the library in the result. The hub page keeps the plain description; body copy and JSON-LD are unchanged.docs/reference/seo.mddocuments the rule.Plan
N/A
Test plan
ruff format/ruff checkclean;tests/unit/api/test_seo_helpers.py63 passed.curl -A bingbot https://anyplot.ai/funnel-basic/python/matplotliband.../python/seabornshow different descriptions starting with the page title and library.🤖 Generated with Claude Code
https://claude.ai/code/session_01SrKzcwZBnref1sWYtdXynu