Skip to content

Commit cf79b3e

Browse files
Ajit Pratap Singhclaude
authored andcommitted
seo(website): add JSON-LD Article to blog posts and BreadcrumbList to docs pages (issue #404)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9a73858 commit cf79b3e

2 files changed

Lines changed: 74 additions & 6 deletions

File tree

website/src/app/blog/[slug]/page.tsx

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,49 @@ export default async function BlogPostPage({ params }: Props) {
5555
const prevPost = currentIndex < allPosts.length - 1 ? allPosts[currentIndex + 1] : null;
5656
const nextPost = currentIndex > 0 ? allPosts[currentIndex - 1] : null;
5757

58+
const jsonLd = {
59+
'@context': 'https://schema.org',
60+
'@type': 'TechArticle',
61+
headline: post.title,
62+
description: `GoSQLX ${post.title} release notes.`,
63+
datePublished: post.date ? `${post.date}T00:00:00Z` : undefined,
64+
dateModified: post.date ? `${post.date}T00:00:00Z` : undefined,
65+
url: `https://gosqlx.dev/blog/${slug}/`,
66+
author: {
67+
'@type': 'Organization',
68+
name: 'GoSQLX',
69+
url: 'https://gosqlx.dev',
70+
},
71+
publisher: {
72+
'@type': 'Organization',
73+
name: 'GoSQLX',
74+
url: 'https://gosqlx.dev',
75+
logo: {
76+
'@type': 'ImageObject',
77+
url: 'https://gosqlx.dev/images/logo.webp',
78+
},
79+
},
80+
image: {
81+
'@type': 'ImageObject',
82+
url: 'https://gosqlx.dev/images/og-image.png',
83+
width: 1200,
84+
height: 630,
85+
},
86+
mainEntityOfPage: {
87+
'@type': 'WebPage',
88+
'@id': `https://gosqlx.dev/blog/${slug}/`,
89+
},
90+
};
91+
5892
return (
59-
<main className="min-h-screen py-20 px-4">
60-
<article className="max-w-3xl mx-auto">
93+
<>
94+
<script
95+
type="application/ld+json"
96+
suppressHydrationWarning
97+
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
98+
/>
99+
<main className="min-h-screen py-20 px-4">
100+
<article className="max-w-3xl mx-auto">
61101
{/* Back link */}
62102
<Link
63103
href="/blog"
@@ -118,8 +158,9 @@ export default async function BlogPostPage({ params }: Props) {
118158
<div />
119159
)}
120160
</nav>
121-
</article>
122-
</main>
161+
</article>
162+
</main>
163+
</>
123164
);
124165
}
125166

website/src/app/docs/[...slug]/page.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,34 @@ export default async function DocPage({ params }: PageProps) {
6565
g.items.some((i) => i.slug === slugStr)
6666
);
6767

68+
const breadcrumbItems: Array<{ '@type': string; position: number; name: string; item: string }> = [
69+
{ '@type': 'ListItem', position: 1, name: 'Home', item: 'https://gosqlx.dev/' },
70+
{ '@type': 'ListItem', position: 2, name: 'Documentation', item: 'https://gosqlx.dev/docs/' },
71+
...(categoryItem
72+
? [{ '@type': 'ListItem', position: 3, name: categoryItem.category, item: 'https://gosqlx.dev/docs/' }]
73+
: []),
74+
{
75+
'@type': 'ListItem',
76+
position: categoryItem ? 4 : 3,
77+
name: doc.title,
78+
item: `https://gosqlx.dev/docs/${slugStr}/`,
79+
},
80+
];
81+
82+
const breadcrumbJsonLd = {
83+
'@context': 'https://schema.org',
84+
'@type': 'BreadcrumbList',
85+
itemListElement: breadcrumbItems,
86+
};
87+
6888
return (
69-
<div className="mx-auto flex max-w-[90rem]">
89+
<>
90+
<script
91+
type="application/ld+json"
92+
suppressHydrationWarning
93+
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
94+
/>
95+
<div className="mx-auto flex max-w-[90rem]">
7096
{/* Sidebar */}
7197
<div className="hidden lg:block w-64 shrink-0">
7298
<Sidebar />
@@ -129,6 +155,7 @@ export default async function DocPage({ params }: PageProps) {
129155
<div className="hidden xl:block w-48 shrink-0 py-10 pr-6">
130156
<Toc headings={headings} />
131157
</div>
132-
</div>
158+
</div>
159+
</>
133160
);
134161
}

0 commit comments

Comments
 (0)