Skip to content

feat(docs): site health + AI-citation fixes (A1, A2, A8 …) - #897

Open
dhananjay6561 wants to merge 26 commits into
keploy:mainfrom
dhananjay6561:feat/ai-citation-health
Open

feat(docs): site health + AI-citation fixes (A1, A2, A8 …)#897
dhananjay6561 wants to merge 26 commits into
keploy:mainfrom
dhananjay6561:feat/ai-citation-health

Conversation

@dhananjay6561

@dhananjay6561 dhananjay6561 commented Aug 7, 2026

Copy link
Copy Markdown
Member

Summary

Site Health + AI-citation / GEO overhaul for the docs site, from the Aug 2026 SEMrush audit (Site Health 84%, AI Search Health 84%) and the schema-type audit. Covers docs tickets A1–A10 / AI1–AI6 plus a full structured-data rework, prioritising template-level fixes that clear hundreds of pages at once.

Scope: docs repo only. Off main, independent of the Core Web Vitals PR (#896). Verified against the served version (v4.0.0).

Audit vs. live docs: the SEMrush export ran on an older main. Several flagged pages no longer exist in v4.0.0 (5 *-filter quickstarts, samples-mux/mysql/nextjs, agile-unit-testing, …), and several "thin" glossary pages are now 1.3k–2.4k words. Rows below reflect the live state.


📊 Ticket status

ID Area What Status
A1 / AI1 SEO AI image on Article schema — fixes ~146 "invalid structured data" ✅ Done
A2 SEO <title> differentiated from on-page <h1> (124 pages) ✅ Done
A3 / AI2 A11Y AI icon-link aria-labels ✅ Already satisfied in theme
A4 / AI5 SEO AI Cross-link pages with a single internal link — "Related" sections on ~190 pages (glossary + running-keploy + quickstart + keploy-cloud + keploy-explained + ci-cd + server) ✅ Done
A5 / AI3 SEO AI Expand thin pages ✅ Done (2 real thin pages expanded; flagged glossary already 1.3k–2.4k words; flagged filter pages deleted)
A7 SEO Unique meta descriptions ✅ Done (surviving pages covered; 4 no longer exist)
A8 A11Y SEO alt on 13 images; samples-echo triple-h1 → single h1 ✅ Done
A9 SEO httphttps doc links; auth-setup title-too-short + dup description ✅ Done
A10 SEO Legacy 1.0.0/2.0.0 are noIndex: true — intentional ✅ Verified, no action
Schema: specialize SEO AI Generic ArticleTechArticle + APIReference (0 generic Article remain) ✅ Done
Schema: @graph SEO AI ~6 fragmented Organization/WebSite/SoftwareApplication nodes → one @id graph ✅ Done
Schema: DefinedTerm SEO AI DefinedTerm on 37 glossary term pages, keyed to the hub's DefinedTermSet @id ✅ Done
Schema: bespoke pages SEO AI / (CollectionPage+ItemList), /about (AboutPage), /leadership (CollectionPage+Person), /security (WebPage+ContactPoint), /privacy-policy (DigitalDocument) ✅ Done
Schema: CI guard SEO scripts/verify-schema-graph.js fails on invalid JSON-LD / dangling @id ✅ Done
AI4: FAQPage AI FAQPage JSON-LD on the 3 FAQ docs ✅ Done
AI4: wider HowTo AI HowTo JSON-LD (visible={false}) on 10 more step-by-step guides (CI/CD, SDK install, Linux/Windows install) — 44 HowTo pages total ✅ Done
Schema: net-new (VideoObject / Course / Event / Offer / SoftwareSourceCode) SEO AI Targets are latent / noIndex / commented components — no rich-result payoff 🚫 Recommend skip
A6 PERF brotli/gzip ⚙️ Vercel/CDN host setting, not source

✅ Changes (highlights)

Structured data — one @id-linked entity graph

  • Each route emitted several disconnected Organization nodes (site-wide + SoftwareApplication.publisher + Article.author + Article.publisher), drifted to two logo URLs. Now declared once in src/schema/siteEntities.js with a stable @id and referenced by @id everywhere. docusaurus.config.js: three ld+json blocks → one @graph.
  • DocItem references the shared @ids; Article @id derives from the trailing-slash canonical URL so it matches other emitters. Added DefinedTerm on glossary term pages.
  • scripts/verify-schema-graph.js — CI guard against invalid JSON-LD / dangling @id.

Structured data — specialization & bespoke pages

  • API-reference docs → APIReference, all other docs → TechArticle; 0 generic Article.
  • A1 image on the Article schema (was computed but never emitted → ~146 "invalid").
  • Bespoke React pages went from zero page schema to CollectionPage/ItemList/AboutPage/WebPage+ContactPoint/DigitalDocument, all @id-linked to the site graph.

AI-citation / GEO

  • FAQPage remark plugin on the 3 FAQ docs.
  • Wider HowTovisible={false} HowTo on the CI/CD, SDK-install and OS-install guides (schema only, no visual change).
  • Cross-linking (A4) — a "Related" section (3–4 contextual internal links) on ~190 previously single-linked pages; glossary terms interlink as a "Related Terms" cluster. Link targets use each page's real route slug (which frequently differs from its filename), verified by a clean build.

SEO / a11y

  • A2 title suffix; A7 unique descriptions; A8 alt text + samples-echo single-h1; A9 https links + descriptive auth-setup title.

🧭 Notes / deviations

  • Net-new emitters recommended skip — VideoObject/Course/Event/Offer/SoftwareSourceCode target latent, commented, or noIndex components; emitting them adds schema with no citation/rich-result payoff.
  • Review/rating schema out of scope — self-hosted AggregateRating/Review violates Google policy; real ratings stay via Organization sameAs (G2/Gartner/Capterra). (Same call as perf(docs): core web vitals — self-host fonts, drop dead assets, defer pixel, add security headers #896.)
  • A6 is a Vercel/CDN host setting, not source.

✅ Verification

  • npm run build succeeds (onBrokenLinks: throw); changed files pass prettier 3.9.6.
  • node scripts/verify-schema-graph.js build (served versions; skips noIndex 1.0.0/2.0.0): 479 pages, 982 JSON-LD blocks, 0 invalid, 0 dangling. @type distribution includes TechArticle 174, HowTo 44, DefinedTerm 37, APIReference 31, FAQPage 3, CollectionPage 2, AboutPage/DigitalDocument/WebPage/DefinedTermSet 1 each, and 0 generic Article (all-versions counts are higher; 1.0.0/2.0.0 keep their own copies).
  • Recommend validating a doc page, the home page, a FAQ page and an install guide in the Rich Results Test, then re-running SEMrush Site Audit + AI Search Health to confirm the DoD (Site Health ≥ 90%, AI ≥ 92%).

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>
Copilot AI lite review requested due to automatic review settings August 7, 2026 10:00
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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 image field 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.

Comment thread src/theme/DocItem/index.js Outdated
Comment thread src/theme/DocItem/index.js
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>
@dhananjay6561 dhananjay6561 self-assigned this Aug 7, 2026
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>

@dhananjay6561 dhananjay6561 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review — feat/ai-citation-health (PR #897)

Reviewed following the four-phase process. This is a large but well-structured PR (+1075/−263, 61 files); the bulk is low-risk template/frontmatter work, and the risky part — a site-wide @id-linked entity graph — is exactly the right architecture. Consolidating the four drifting Organization nodes into one siteEntities.js source of truth referenced by @id, driving GET_STARTED_PATHS from the same data the cards render, and the defensive link-filter in glossary.js are all strong calls. Build passes under onBrokenLinks: throw and the schema verifier reports 0 invalid / 0 dangling.

No blocking issues. I left inline notes: one 🟡 on the CI guard's dangling-@id detection (a real coverage gap, though it doesn't affect this PR's current bare-ref schema), one 🟡 on a URL-casing mismatch in the leadership schema, plus a 💡 on FAQ answer-text quality and a 🟢 on a self-contradicting comment. None need to block merge.

🎉 src/schema/siteEntities.js + the @id derivation from the trailing-slash canonical in DocItem is the standout — it fixes the actual root cause (fragmented, drifted entities) rather than papering over the symptoms, and the verify-schema-graph.js guard to keep it that way is the right instinct.

Comment thread scripts/verify-schema-graph.js
Comment thread src/remark/remarkFaqSchema.js
Comment thread src/remark/remarkFaqSchema.js
Comment thread src/pages/leadership.js
Add a "Related" section (3–4 contextual internal links) to running-keploy feature docs that had 
only one internal link. Links use each page real route slug, verified by a clean build under 
onBrokenLinks: throw.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Add a "Related" section to quickstart sample-app guides, linking same-language / same-datastore 
samples and the language recommendation page. Routes verified against the build (slugs differ from 
filenames here).

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Add a "Related" section to keploy-cloud pages that had a single internal link, linking sibling 
cloud features. Build-verified routes.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Add a "Related" section to keploy-explained pages, linking sibling concept/FAQ/setup docs. 
Build-verified routes.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Cross-link the GitHub, GitLab and Jenkins CI guides to each other and to the API-test CI/CD setup. 
Build-verified routes.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Add a "Related" section to the install pages and language SDK pages, cross-linking the SDKs and 
install guides. Build-verified routes.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Emit schema.org HowTo JSON-LD (visible={false}, no visual change) on the GitHub, GitLab and Jenkins 
guides so AI engines can extract the install-and-run steps.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Emit HowTo JSON-LD (visible={false}) on the Go, Java, JavaScript and Python SDK pages covering 
agent setup and coverage merge steps.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Emit HowTo JSON-LD (visible={false}) on the Linux, Windows and native Windows/WSL install pages.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
Add gzip, Mux, Prisma, JWT, unbuggy, webhook, datastore, async, boolean,
quickstarts and _Transform to the Vale accept vocabulary. These appear in the
new "Related" link text and in prettier-normalized code lines, and are valid
terms the Vale spell-check does not recognise.

Signed-off-by: dhananjay6561 <dhananjayaggarwal6561@gmail.com>
@dhananjay6561
dhananjay6561 force-pushed the feat/ai-citation-health branch 2 times, most recently from da86911 to 409fbff Compare August 10, 2026 14:49
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.

2 participants