Skip to content

Commit e6f719f

Browse files
slayerjainclaude
andcommitted
seo: HowTo schema, glossary DefinedTermSet, docs landing fixes
Audit findings on keploy.io/docs and follow-up coverage. Critical fixes: - /docs/ landing was rendering zero H1, with title "Keploy Documentation" (20 chars) and description "API Test Generator Tool" (23 chars). Both too short to capture docs intent (install, capture, replay, SDK). Added an sr-only H1 plus a longer Layout title/description on src/pages/index.js ("Keploy Documentation — Install, Capture & Replay API Tests" + a 159-char description covering install, capture, CI replay, SDK references). - src/pages/about.js shipped zero JSON-LD because src/pages/* are not covered by the docs schema plugin. Inlined Article + BreadcrumbList JSON-LD via @docusaurus/Head. - src/pages/concepts/reference/glossary.js shipped zero JSON-LD too. Now emits a single DefinedTermSet from the entire glossaryEntries data, with one DefinedTerm per glossary entry. Mirrors the pattern in landing's /what-is-api-testing layout. - Docusaurus sitemap noIndex on 1.0.0 / 2.0.0 archives + ignorePatterns to drop /tags/** and /1.0.0/** /2.0.0/** from the generated sitemap. Reduces crawl-budget dilution; preserves the recently-added priority bucket comments above the sitemap config. HowTo schema rollout: - New src/components/HowTo.js wrapper. API: <HowTo name="Install Keploy on Linux" totalTime="PT5M" tools={[...]} supplies={[...]} steps={[{name, text, url}, ...]} visible={true|false} /> Emits valid HowTo JSON-LD via @docusaurus/Head and (when visible) renders a numbered <ol>. Use visible={false} on pages that already render the steps in prose to avoid duplicate UI. - Applied to versioned_docs/version-4.0.0/server/installation.md (visible HowTo above the existing prose). - Applied to all 32 quickstart pages in versioned_docs/version-4.0.0/quickstart with visible={false} (existing tutorial prose remains; only schema is added). SDK-installation title alignment: - /docs/server/sdk-installation/go|python|javascript pages had H1/title "Merge Test Coverage Data" while the URL says "sdk-installation". Title rewritten to "Keploy [Language] SDK — Install & Merge Test Coverage" so URL and content topic align without renaming the route or moving files. java.md is unchanged here — upstream main has rewritten that file as the Enterprise dynamic-deduplication agent guide, so the SDK-install framing no longer applies to it. Built + verified: `npx docusaurus build` produces a clean static build. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5c88544 commit e6f719f

41 files changed

Lines changed: 1286 additions & 10 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docusaurus.config.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,13 @@ module.exports = {
365365
label: "1.0.0",
366366
path: "1.0.0",
367367
banner: "unmaintained",
368+
noIndex: true,
368369
},
369370
"2.0.0": {
370371
label: "2.0.0",
371372
path: "2.0.0",
372373
banner: "unmaintained",
374+
noIndex: true,
373375
},
374376
},
375377
onlyIncludeVersions: ["1.0.0", "2.0.0", "4.0.0"],
@@ -464,6 +466,17 @@ module.exports = {
464466
// 0.5 → /docs/concepts/reference/glossary/* (long-tail
465467
// glossary; noindexed legacy versions excluded via
466468
// netlify headers + robots.txt)
469+
//
470+
// Also exclude auto-generated tag indexes and the unmaintained
471+
// 1.0.0 / 2.0.0 doc versions from the sitemap. Those versions
472+
// additionally carry `noIndex: true` via their `versions` config
473+
// above; excluding from the sitemap signals that they should not
474+
// be ranked at all.
475+
ignorePatterns: [
476+
"/tags/**",
477+
"/1.0.0/**",
478+
"/2.0.0/**",
479+
],
467480
createSitemapItems: async (params) => {
468481
const {defaultCreateSitemapItems, ...rest} = params;
469482
const items = await defaultCreateSitemapItems(rest);

src/components/HowTo.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import React from "react";
2+
import Head from "@docusaurus/Head";
3+
4+
/**
5+
* HowTo schema.org wrapper for Docusaurus MDX pages.
6+
*
7+
* Emits valid schema.org/HowTo JSON-LD into <head> and (optionally) renders a
8+
* matching numbered <ol> of visible steps. Authors can pass `visible={false}`
9+
* when the prose below already renders the steps so the JSON-LD is the only
10+
* change to the page.
11+
*
12+
* Required HowTo fields per Google: name, step (array of HowToStep with name + text).
13+
* Optional: totalTime (ISO 8601 duration), estimatedCost (MonetaryAmount), tool, supply.
14+
*
15+
* Example:
16+
* <HowTo
17+
* name="Install Keploy on Linux"
18+
* totalTime="PT5M"
19+
* estimatedCost={{currency: "USD", value: "0"}}
20+
* tools={["bash", "curl"]}
21+
* supplies={["Linux machine with kernel >= 5.10"]}
22+
* steps={[
23+
* {name: "Download", text: "Run: curl ...", url: "#download"},
24+
* {name: "Install", text: "Run: sudo install ...", url: "#install"},
25+
* ]}
26+
* visible={false}
27+
* />
28+
*/
29+
export default function HowTo({
30+
name,
31+
description,
32+
totalTime,
33+
estimatedCost,
34+
tools,
35+
supplies,
36+
image,
37+
steps,
38+
visible = true,
39+
}) {
40+
if (!name || !Array.isArray(steps) || steps.length === 0) {
41+
// Component is a no-op without the minimum required fields.
42+
return null;
43+
}
44+
45+
const schema = {
46+
"@context": "https://schema.org",
47+
"@type": "HowTo",
48+
name,
49+
step: steps.map((s, i) => {
50+
const step = {
51+
"@type": "HowToStep",
52+
position: i + 1,
53+
name: s.name || `Step ${i + 1}`,
54+
text: s.text || "",
55+
};
56+
if (s.url) step.url = s.url;
57+
if (s.image) step.image = s.image;
58+
return step;
59+
}),
60+
};
61+
62+
if (description) schema.description = description;
63+
if (totalTime) schema.totalTime = totalTime;
64+
if (image) schema.image = image;
65+
if (estimatedCost && estimatedCost.value !== undefined) {
66+
schema.estimatedCost = {
67+
"@type": "MonetaryAmount",
68+
currency: estimatedCost.currency || "USD",
69+
value: String(estimatedCost.value),
70+
};
71+
}
72+
if (Array.isArray(tools) && tools.length > 0) {
73+
schema.tool = tools.map((t) =>
74+
typeof t === "string" ? {"@type": "HowToTool", name: t} : t,
75+
);
76+
}
77+
if (Array.isArray(supplies) && supplies.length > 0) {
78+
schema.supply = supplies.map((s) =>
79+
typeof s === "string" ? {"@type": "HowToSupply", name: s} : s,
80+
);
81+
}
82+
83+
return (
84+
<>
85+
<Head>
86+
<script type="application/ld+json">{JSON.stringify(schema)}</script>
87+
</Head>
88+
{visible && (
89+
<section
90+
aria-label={name}
91+
style={{
92+
border: "1px solid var(--ifm-color-emphasis-200)",
93+
borderRadius: "12px",
94+
padding: "1rem 1.25rem",
95+
margin: "1rem 0 1.5rem",
96+
background: "var(--ifm-background-surface-color)",
97+
}}
98+
>
99+
<h3 style={{marginTop: 0}}>{name}</h3>
100+
{description && <p>{description}</p>}
101+
<ol>
102+
{steps.map((s, i) => (
103+
<li key={i} id={s.url && s.url.startsWith("#") ? s.url.slice(1) : undefined}>
104+
<strong>{s.name || `Step ${i + 1}`}</strong>
105+
{s.text && <div>{s.text}</div>}
106+
</li>
107+
))}
108+
</ol>
109+
</section>
110+
)}
111+
</>
112+
);
113+
}

src/pages/about.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,44 @@
11
import React from "react";
22
import Layout from "@theme/Layout";
3+
import Head from "@docusaurus/Head";
34
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
45
import useBaseUrl from "@docusaurus/useBaseUrl";
56

7+
// Custom React pages under src/pages/ are not covered by the docs schema
8+
// plugin — add Article + BreadcrumbList JSON-LD inline so the page is
9+
// machine-readable for search engines and AI crawlers.
10+
const aboutStructuredData = [
11+
{
12+
"@context": "https://schema.org",
13+
"@type": "Article",
14+
headline: "About the Keploy Documentation",
15+
description:
16+
"Information about Keploy's documentation, contribution guidelines, and licensing.",
17+
url: "https://keploy.io/docs/about",
18+
publisher: {
19+
"@type": "Organization",
20+
name: "Keploy",
21+
logo: {
22+
"@type": "ImageObject",
23+
url: "https://keploy.io/docs/img/favicon.png",
24+
},
25+
},
26+
mainEntityOfPage: {
27+
"@type": "WebPage",
28+
"@id": "https://keploy.io/docs/about",
29+
},
30+
},
31+
{
32+
"@context": "https://schema.org",
33+
"@type": "BreadcrumbList",
34+
itemListElement: [
35+
{"@type": "ListItem", position: 1, name: "Home", item: "https://keploy.io"},
36+
{"@type": "ListItem", position: 2, name: "Docs", item: "https://keploy.io/docs"},
37+
{"@type": "ListItem", position: 3, name: "About", item: "https://keploy.io/docs/about"},
38+
],
39+
},
40+
];
41+
642
function About() {
743
const context = useDocusaurusContext();
844
const {siteConfig = {}} = context;
@@ -12,6 +48,13 @@ function About() {
1248
permalink="/about"
1349
description="User General Information about Keploy's Documentation"
1450
>
51+
<Head>
52+
{aboutStructuredData.map((schema, i) => (
53+
<script key={i} type="application/ld+json">
54+
{JSON.stringify(schema)}
55+
</script>
56+
))}
57+
</Head>
1558
<main className="margin-vert--lg container">
1659
<h1>About the docs</h1>
1760
<div className="margin-bottom--lg">

src/pages/concepts/reference/glossary.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,47 @@
11
import React, {useState, useMemo} from "react";
22
import Layout from "@theme/Layout";
3+
import Head from "@docusaurus/Head";
34
import BackToTopButton from "@theme/BackToTopButton";
45

56
import {glossaryEntries} from "../../../../static/data/glossaryEntries";
67
import GlossaryCard from "../../../components/GlossaryCard";
78

9+
// SEO/GEO: turn each glossary entry into a DefinedTerm inside a single
10+
// DefinedTermSet so AI engines can cite individual definitions and engines
11+
// can surface them as featured-snippet definitions. Mirrors the pattern in
12+
// landing/app/(default)/what-is-api-testing/layout.tsx.
13+
const allGlossaryItems = Object.values(glossaryEntries).flat();
14+
const SITE = "https://keploy.io";
15+
16+
const glossaryStructuredData = [
17+
{
18+
"@context": "https://schema.org",
19+
"@type": "DefinedTermSet",
20+
"@id": `${SITE}/docs/concepts/reference/glossary#termset`,
21+
name: "Keploy Software Testing Glossary",
22+
description:
23+
"Definitions for software testing, test automation, and quality engineering terminology, maintained by the Keploy documentation team.",
24+
url: `${SITE}/docs/concepts/reference/glossary`,
25+
hasDefinedTerm: allGlossaryItems.map((entry) => ({
26+
"@type": "DefinedTerm",
27+
name: entry.name,
28+
description: entry.description,
29+
url: `${SITE}${entry.link}`,
30+
inDefinedTermSet: `${SITE}/docs/concepts/reference/glossary#termset`,
31+
})),
32+
},
33+
{
34+
"@context": "https://schema.org",
35+
"@type": "BreadcrumbList",
36+
itemListElement: [
37+
{"@type": "ListItem", position: 1, name: "Home", item: SITE},
38+
{"@type": "ListItem", position: 2, name: "Docs", item: `${SITE}/docs`},
39+
{"@type": "ListItem", position: 3, name: "Concepts", item: `${SITE}/docs/concepts`},
40+
{"@type": "ListItem", position: 4, name: "Glossary", item: `${SITE}/docs/concepts/reference/glossary`},
41+
],
42+
},
43+
];
44+
845
function Glossary() {
946
const [selectedletter, setselectedletter] = useState([]);
1047

@@ -37,10 +74,17 @@ function Glossary() {
3774

3875
return (
3976
<Layout
40-
title="Glossary"
77+
title="Software Testing Glossary — Keploy Documentation"
4178
permalink="/reference/glossary"
42-
description="A glossary of terms related to software testing and development."
79+
description="Definitions for software testing, test automation, and QA terminology. Acceptance, agile unit, BDD, beta, black-box testing and more."
4380
>
81+
<Head>
82+
{glossaryStructuredData.map((schema, i) => (
83+
<script key={i} type="application/ld+json">
84+
{JSON.stringify(schema)}
85+
</script>
86+
))}
87+
</Head>
4488
<main className="container mx-auto my-12 px-4 sm:px-6 lg:px-8">
4589
<div className="mb-12 text-center">
4690
<h1 className="text-4xl font-extrabold tracking-tight sm:text-5xl">

src/pages/index.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ export default function Home() {
6262
},
6363
}
6464
: null;
65+
// SEO: docs landing previously rendered with title "Keploy Documentation" (20c)
66+
// and meta description "API Test Generator Tool" (23c). Both were too short
67+
// to capture the intent of a docs visitor (install, capture, replay, SDK).
68+
const docsHomeTitle = "Keploy Documentation — Install, Capture & Replay API Tests";
69+
const docsHomeDescription = "Install Keploy in 5 minutes, capture real API traffic with eBPF, and replay it as deterministic tests in CI. Quickstarts, SDK references, and integration guides.";
70+
6571
return (
6672
<div className="main">
6773
<Head>
@@ -78,10 +84,11 @@ export default function Home() {
7884
</Head>
7985
<Layout
8086
className="mx-auto my-2 w-full max-w-screen-lg px-8 shadow-none"
81-
title={`${siteConfig.title}`}
82-
description={`${siteConfig.tagline}`}
87+
title={docsHomeTitle}
88+
description={docsHomeDescription}
8389
>
8490
<main className="mx-auto max-w-screen-lg p-6 md:p-10">
91+
<h1 className="sr-only">{docsHomeTitle}</h1>
8592

8693
<GetStartedPaths />
8794
<TestingCapabilities />

versioned_docs/version-4.0.0/quickstart/csharp-dotnet-postgres.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,38 @@ keywords:
1818
- API Test generator
1919
- Auto Testcase generation
2020
---
21+
import HowTo from '@site/src/components/HowTo';
22+
23+
<HowTo
24+
name="Sample CRUD App (CSharp) — record and replay tests with Keploy"
25+
description="Clone the sample app, run it under Keploy to capture API traffic, then replay the recorded testcases."
26+
totalTime="PT10M"
27+
estimatedCost={{currency: "USD", value: "0"}}
28+
tools={["Keploy CLI", "Docker", "git"]}
29+
visible={false}
30+
steps={[
31+
{
32+
name: "Install Keploy",
33+
text: "Install the Keploy CLI on Linux/WSL using the install script from https://keploy.io/install.sh.",
34+
},
35+
{
36+
name: "Clone the sample app",
37+
text: "Clone the sample repo referenced on this page and install its dependencies.",
38+
},
39+
{
40+
name: "Start dependencies (database, etc.)",
41+
text: "Bring up any Docker services the app needs (databases, message queues) before recording.",
42+
},
43+
{
44+
name: "Record API calls",
45+
text: "Run keploy record -c \"CMD_TO_RUN_APP\" and exercise the app's endpoints (curl, Postman) to capture testcases and mocks.",
46+
},
47+
{
48+
name: "Replay tests",
49+
text: "Run keploy test -c \"CMD_TO_RUN_APP\" --delay 10 to replay the recorded testcases and detect regressions.",
50+
},
51+
]}
52+
/>
2153

2254
## Running App Locally on Linux/WSL 🐧
2355

versioned_docs/version-4.0.0/quickstart/express-postgresql-prisma.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,38 @@ keywords:
1717
- API Test generator
1818
- Auto Testcase generation
1919
---
20+
import HowTo from '@site/src/components/HowTo';
21+
22+
<HowTo
23+
name="Express + PostgreSQL + Prisma Sample Application — record and replay tests with Keploy"
24+
description="Clone the sample app, run it under Keploy to capture API traffic, then replay the recorded testcases."
25+
totalTime="PT10M"
26+
estimatedCost={{currency: "USD", value: "0"}}
27+
tools={["Keploy CLI", "Docker", "git"]}
28+
visible={false}
29+
steps={[
30+
{
31+
name: "Install Keploy",
32+
text: "Install the Keploy CLI on Linux/WSL using the install script from https://keploy.io/install.sh.",
33+
},
34+
{
35+
name: "Clone the sample app",
36+
text: "Clone the sample repo referenced on this page and install its dependencies.",
37+
},
38+
{
39+
name: "Start dependencies (database, etc.)",
40+
text: "Bring up any Docker services the app needs (databases, message queues) before recording.",
41+
},
42+
{
43+
name: "Record API calls",
44+
text: "Run keploy record -c \"CMD_TO_RUN_APP\" and exercise the app's endpoints (curl, Postman) to capture testcases and mocks.",
45+
},
46+
{
47+
name: "Replay tests",
48+
text: "Run keploy test -c \"CMD_TO_RUN_APP\" --delay 10 to replay the recorded testcases and detect regressions.",
49+
},
50+
]}
51+
/>
2052

2153
import InstallReminder from '@site/src/components/InstallReminder';
2254
import SectionDivider from '@site/src/components/SectionDivider';

0 commit comments

Comments
 (0)