Skip to content

Commit 09e48ef

Browse files
committed
seo: add WebAPI + APIReference schema.org JSON-LD to docs
SiteStructuredData now emits a WebAPI block covering the full SharpAPI REST API (name, description, documentation URL, termsOfService, provider). New ApiReferenceJsonLd component emits APIReference (TechArticle subtype) on every /api-reference/* page, using the MDX frontmatter title and description. Covers all 35 existing endpoint pages automatically.
1 parent f88e9d6 commit 09e48ef

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

app/[lang]/[[...mdxPath]]/page.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { generateStaticParamsFor, importPage } from 'nextra/pages'
22
import { useMDXComponents } from '../../../mdx-components'
3-
import { PageBreadcrumb } from '../../../components/StructuredData'
3+
import { ApiReferenceJsonLd, PageBreadcrumb } from '../../../components/StructuredData'
44

55
export const generateStaticParams = generateStaticParamsFor('mdxPath')
66

@@ -34,9 +34,19 @@ export default async function Page(props) {
3434
const pathname = params.mdxPath
3535
? `/${params.lang}/${params.mdxPath.join('/')}`
3636
: `/${params.lang}`
37+
const isApiRef = params.mdxPath?.[0] === 'api-reference'
38+
const pageUrl = `https://docs.sharpapi.io${pathname}`
39+
3740
return (
3841
<>
3942
<PageBreadcrumb pathname={pathname} title={metadata?.title as string | undefined} />
43+
{isApiRef && metadata?.title && (
44+
<ApiReferenceJsonLd
45+
title={String(metadata.title)}
46+
description={String(metadata.description ?? '')}
47+
url={pageUrl}
48+
/>
49+
)}
4050
<Wrapper toc={toc} metadata={metadata}>
4151
<MDXContent {...props} params={params} />
4252
</Wrapper>

components/StructuredData.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
*
44
* Emitted on every docs page via app/[lang]/layout.tsx:
55
* - Organization (sitewide)
6-
* - WebSite with SearchAction (enables in-search sitelinks search box)
6+
* - WebSite (sitewide)
7+
* - WebAPI (sitewide — describes the SharpAPI REST API as a machine-readable entity)
8+
*
9+
* Emitted per API reference page via app/[lang]/[[...mdxPath]]/page.tsx:
10+
* - APIReference (TechArticle subtype) for each /api-reference/* page
711
*
812
* BreadcrumbList is generated per-page from the pathname; see PageBreadcrumb.
913
*/
@@ -41,10 +45,58 @@ export function SiteStructuredData() {
4145
'publisher': { '@type': 'Organization', 'name': 'SharpAPI', 'url': MAIN_URL },
4246
})}
4347
/>
48+
<script
49+
type="application/ld+json"
50+
dangerouslySetInnerHTML={jsonLd({
51+
'@context': 'https://schema.org',
52+
'@type': 'WebAPI',
53+
'name': 'SharpAPI REST API',
54+
'description': 'Real-time sports betting odds API with +EV detection, arbitrage alerts, and SSE streaming across 43 sportsbooks.',
55+
'url': `${SITE_URL}/en/api-reference/overview`,
56+
'documentation': SITE_URL,
57+
'termsOfService': `${MAIN_URL}/terms`,
58+
'provider': {
59+
'@type': 'Organization',
60+
'name': 'SharpAPI',
61+
'url': MAIN_URL,
62+
},
63+
})}
64+
/>
4465
</>
4566
)
4667
}
4768

69+
interface ApiReferenceJsonLdProps {
70+
title: string
71+
description: string
72+
url: string
73+
}
74+
75+
export function ApiReferenceJsonLd({ title, description, url }: ApiReferenceJsonLdProps) {
76+
return (
77+
<script
78+
type="application/ld+json"
79+
dangerouslySetInnerHTML={jsonLd({
80+
'@context': 'https://schema.org',
81+
'@type': 'APIReference',
82+
'name': title,
83+
'description': description,
84+
'url': url,
85+
'isPartOf': {
86+
'@type': 'WebAPI',
87+
'name': 'SharpAPI REST API',
88+
'url': `${SITE_URL}/en/api-reference/overview`,
89+
'provider': {
90+
'@type': 'Organization',
91+
'name': 'SharpAPI',
92+
'url': MAIN_URL,
93+
},
94+
},
95+
})}
96+
/>
97+
)
98+
}
99+
48100
interface PageBreadcrumbProps {
49101
pathname: string
50102
title?: string

0 commit comments

Comments
 (0)