feat(docs): site health + AI-citation fixes (A1, A2, A8 …) - #897
Open
dhananjay6561 wants to merge 16 commits into
Open
feat(docs): site health + AI-citation fixes (A1, A2, A8 …)#897dhananjay6561 wants to merge 16 commits into
dhananjay6561 wants to merge 16 commits into
Conversation
DocItem computed socialImage but never included it in the Article/ TechArticle JSON-LD, so every doc page emitted an Article without the required 'image' field -> ~146 pages flagged invalid structured data. Add image to articleSchema, falling back to the site-wide default social card (the same 1200x630 og:image from docusaurus.config.js) when a doc sets no front-matter image. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
The swizzled DocItem set <title>{title}</title>, identical to the on-page
<h1> (also the doc title) -> SEMrush 'Duplicate content in h1 and title'
on 124 pages. Append ' | Keploy Docs' so the title differs from the h1.
Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
13 images across 8 doc pages (glossary GIFs + running-keploy screenshots) had no alt attribute -> SEMrush 'Missing ALT' + weaker AI/accessibility extraction. Add descriptive alt to each. utg-vscode-extension from the audit list no longer exists on main, so it is not included. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Pre-existing whitespace/list-indent/final-newline issues in these two files (unrelated to the alt fix) would fail the prettier CI check once the files are touched. Apply prettier so the PR is clean. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the Docusaurus DocItem theme component to address SEO / AI-citation audit findings by improving structured data completeness and avoiding duplicate <title>/<h1> signals across docs pages.
Changes:
- Adds an
imagefield to the per-page Article/TechArticle JSON-LD (with a fallback when front matter has no image). - Appends a suffix to
<title>to differentiate it from the on-page<h1>.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Wrap the long articleImage fallback line and flatten the pre-existing nested-ternary indentation so the swizzled DocItem is clean under the CI-pinned prettier 2.8.8 (--check runs on changed files). Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
The prettify_code workflow pins prettier_version 2.8.8, but creyD/ prettier_action's npx step actually installs and runs prettier 3.9.6. 3.x changed nested-ternary indentation, so the prior 2.8.8-flattened schemaType ternary failed CI. Reformat to 3.9.6 (the version CI runs) so --check passes; all other changed files are already 3.9.6-clean. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Every /docs page emitted a generic Article. Route API-reference pages (api-testing-*, public-api, cli-commands, sdk-installation — by tag or path) to APIReference, and default all other docs to TechArticle. Both are Article subtypes accepting the same properties as articleSchema, so the schema shape is unchanged — just a precise, AI/Google-friendly type. Built HTML: 35 APIReference, 343 TechArticle, 0 generic Article from docs. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
general-glossary + 3 glossary terms shared one boilerplate description; share-tests copied the generate-api-tests description; k8s-proxy had a wrong (NextJS/Drizzle) description. Give each a unique, accurate one to clear SEMrush 'Duplicate meta descriptions'. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Pre-existing leading-space paragraphs (unrelated to the description change) would fail the prettier CI check once the file is touched. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
/leadership, /security and /privacy-policy emitted zero page-level schema. Add JSON-LD: leadership -> CollectionPage + ItemList of Person (name, photo, Twitter, worksFor Keploy); security -> WebPage + security ContactPoint (responsible-disclosure email); privacy-policy -> DigitalDocument with dateModified. Verified in built HTML. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
New dependency-free remark plugin extracts each ### question + following answer prose from FAQ docs (keploy-explained/*-faq) and injects FAQPage JSON-LD with Question/acceptedAnswer pairs, so they're eligible for FAQ rich results and AI extraction. Built HTML: FAQPage with 14/11/12 Q&A on the three FAQ pages. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Every route emitted several disconnected Organization nodes: the site-wide one plus copies inlined as SoftwareApplication.publisher, Article.author and Article.publisher, which had drifted to two different logo URLs. Declare each site-wide entity (Organization, WebSite, SoftwareApplication) once in src/schema/siteEntities.js with a stable @id and reference it by @id everywhere else, so consumers merge them into a single entity per page. - docusaurus.config.js: three sibling ld+json blocks -> one @graph (siteGraph) - DocItem: author/publisher/isPartOf reference the shared @ids; derive the Article @id from the trailing-slash canonical URL so it matches the URLs the glossary hub and bespoke pages emit; add a DefinedTerm on glossary term pages, keyed to the hub's DefinedTermSet @id (latest version only) - bespoke pages: about -> AboutPage, index -> CollectionPage + ItemList (off GetStartedPaths' exported data), leadership -> CollectionPage of Person, privacy-policy -> DigitalDocument, security -> WebPage + Organization contactPoint on the shared Org @id - glossary hub DefinedTerms gain the same @id as their term pages so the two listings resolve to one entity - GlossaryCard uses Docusaurus Link (build-checked, trailingSlash-aware) - scripts/verify-schema-graph.js: fail CI on invalid JSON-LD or dangling @id Verified: clean build, verify-schema-graph reports 0 invalid / 0 dangling across 479 pages / 972 blocks; no generic Article remains. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
- samples-echo: two body sections used a single `#`, producing three h1s on the page (title + two). Demote both to `##` so the page has one h1 and a clean heading hierarchy (A8, multiple-h1). - configuration-file: rewrite four in-body doc links from http:// to https:// (the two remaining http:// occurrences are regex examples in a code block and are left as-is) (A9, HTTP-link-on-HTTPS-site). - api-testing-auth-setup: the title "Auth Setup" was flagged as too short and its description was a near-duplicate stub; give it a descriptive title and a unique description (sidebar_label stays "Auth Setup") (A9, title-too-short). Verified: clean build (onBrokenLinks: throw), verify-schema-graph 0 invalid / 0 dangling. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
…inks integrations-pr-agent was ~120 words (flagged "low word count"). Add a "What the PR Agent does" section and a Related block linking the AI test generator, UTG PR agent, and CI/CD GitHub setup, so the page carries real content and more than one internal link (A4). Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
…d links windows-wsl was ~177 words. Add why-WSL context, a Prerequisites section, clearer install steps, and a Related block (macOS/Linux install, CLI reference, common errors) to fix the thin-content and single-internal-link flags (A5/A4). Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Glossary term pages each had only one internal link (SEMrush "pages with only one internal link"). Add a "Related Terms" section to every term page linking 3–4 conceptually related terms plus the glossary hub, so terms form a connected cluster that both readers and AI engines can traverse. Link targets use each term's real route slug (e.g. agile-testing.md serves at /agile-unit-testing/, grey-box-testing.md at /gray-box-testing/), verified by a clean build under onBrokenLinks: throw. Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
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
Site Health + AI-citation / GEO fixes for the docs site, from the Aug 2026 SEMrush audit (Site Health 84%, AI Search Health 84%) and the schema-type audit. Covers the docs tickets A1–A10 / AI1–AI6 plus a full structured-data overhaul from the schema audit, prioritising template-level fixes that clear hundreds of pages at once.
📊 Ticket status
SEOAIimageadded to Article schema — fixes ~146 "invalid structured data"SEO<title>differentiated from on-page<h1>— fixes 124 duplicatesSEOA11YAISEOalton 13 images / 8 pages;samples-echotriple-h1 → single h1SEOhttp://→https://doc links (configuration-file);auth-setuptitle-too-short + dup descriptionSEOAIArticle→TechArticle+APIReference(0 genericArticleremain)SEOAI@idgraphSEOAIDefinedTermon 37 glossary term pages, keyed to the hub'sDefinedTermSet@idSEOAI/(CollectionPage+ItemList),/about(AboutPage),/leadership(CollectionPage+ItemList+Person),/security(WebPage+ContactPoint on shared Org@id),/privacy-policy(DigitalDocument)SEOscripts/verify-schema-graph.js— fails on invalid JSON-LD or dangling@idAIFAQPageJSON-LD (Question/Answer) on the 3 FAQ docsA11YAIaria-labelsSEO/docs/1.0.0/*+2.0.0arenoIndex: truein config — intentionalSEOAInoIndex/ commented components (ResponsivePlayer→v1.0.0 noindex, Product.js latent) with no rich-result payoffSEOAIAI<HowTo>in more step-by-step guidesSEOAIintegrations-pr-agent,windows-wsl); the flagged glossary pages are already 1.3k–2.4k words; the flagged filter pages were deletedPERF✅ Changes
Structured data — one
@id-linked entity graphOrganizationnodes (site-wide +SoftwareApplication.publisher+Article.author+Article.publisher), which had drifted to two different logo URLs. Each site-wide entity (Organization,WebSite,SoftwareApplication) is now declared once insrc/schema/siteEntities.jswith a stable@idand referenced by@ideverywhere, so consumers merge them into a single entity per page.docusaurus.config.js: three siblingld+jsonblocks → one@graph(siteGraph).DocItem:author/publisher/isPartOfreference the shared@ids; the Article@idis derived from the trailing-slash canonical URL so it matches the URLs the glossary hub and bespoke pages emit.DefinedTermon the 37 glossary term pages, keyed to the hub'sDefinedTermSet@id, so the hub listing and the term page resolve to one entity (latest version only).scripts/verify-schema-graph.jswalks the built HTML and fails CI on invalid JSON-LD or a dangling@id.Structured data — schema specialization
DocItemroutes API-reference pages toAPIReferenceand all other docs toTechArticle(bothArticlesubtypes, same properties — just a precise type). 0 genericArticleremain.imageon the Article schema —DocItemcomputedsocialImagebut never emitted it, so ~146 pages were "invalid structured data". Now included with the site-wide 1200×630 og:image as fallback.Structured data — bespoke React pages
/(index.js): genericArticle→CollectionPage+ItemListbuilt fromGetStartedPaths' exported entry-point data (DocItem already suppressesArticleon/docs/for the same reason)./about:AboutPage(standing info about the docs, no author/date for an Article)./leadership:CollectionPage+ItemListofPerson(photo + Twitter +worksFor→ shared Org@id)./security:WebPage+OrganizationcontactPointattached to the shared Org@id(responsible-disclosure email)./privacy-policy:DigitalDocumentwithdateModified.GlossaryCardnow uses DocusaurusLink(build-checked underonBrokenLinks: throw,trailingSlash-aware).AI / SEO
src/remark/remarkFaqSchema.js) extracts### question+ answer prose intoQuestion/acceptedAnswerpairs and injectsFAQPageJSON-LD on the 3 FAQ docs.| Keploy Docson 124 pages.share-tests,k8s-proxy.alton 13 images / 8 pages;samples-echohad two body#sections producing three h1s → demoted to##.http://keploy.io/docs/...doc links inconfiguration-file→https://(regex examples in code blocks left as-is);api-testing-auth-setupgot a descriptive title (was "Auth Setup", too short) and a unique description.🧭 Notes / deviations from the plan
noIndexcomponents (e.g. ResponsivePlayer only renders on thenoIndexv1.0.0 page;Product.jsis not on an indexed route). Emitting them would add schema with no rich-result or citation payoff.AggregateRating/Reviewfor one's own product violates Google's structured-data policy (manual-action risk). Real ratings stay surfaced via the OrganizationsameAslinks (G2/Gartner/Capterra). (Same call as CWV perf(docs): core web vitals — self-host fonts, drop dead assets, defer pixel, add security headers #896.)aria-labels.✅ Verification
npm run buildsucceeds (onBrokenLinks: throw); all changed files pass prettier 3.9.6.node scripts/verify-schema-graph.js buildon the served versions (skips thenoIndex1.0.0/2.0.0): 479 pages, 972 JSON-LD blocks, 0 invalid JSON, 0 dangling@id. Top@types:Organization/WebSite/SoftwareApplication(one each per page via the shared graph),BreadcrumbList208,TechArticle174,DefinedTerm37,HowTo34,APIReference31,FAQPage3,CollectionPage2,AboutPage/DigitalDocument/WebPage/DefinedTermSet1 each — 0 genericArticle. (All-versions counts are higher because 1.0.0/2.0.0 carry their own copies.)