From a5abd56250a0713a3ef057497f225f231b224aae Mon Sep 17 00:00:00 2001 From: Lasim Date: Thu, 14 Aug 2025 08:24:09 +0200 Subject: [PATCH 1/7] feat(structured-data): implement structured data generation for documentation pages and site-wide schemas --- app/[[...slug]]/page.tsx | 87 +++++++++++++------ app/layout.tsx | 12 +++ lib/seo-utils.ts | 3 - lib/structured-data.ts | 178 +++++++++++++++++++++++++++++++++++++++ package-lock.json | 9 +- package.json | 3 +- 6 files changed, 263 insertions(+), 29 deletions(-) create mode 100644 lib/structured-data.ts diff --git a/app/[[...slug]]/page.tsx b/app/[[...slug]]/page.tsx index 1c390be..4e4e1f1 100644 --- a/app/[[...slug]]/page.tsx +++ b/app/[[...slug]]/page.tsx @@ -9,6 +9,7 @@ import { getFinalPageTitle } from '@/lib/h1-extractor'; import { readFile } from 'fs/promises'; import { getMDXComponents } from '@/mdx-components'; import { homeOptions, docsOptions } from '../layout.config'; +import { generateTechArticleSchema, generateBreadcrumbSchema, combineSchemas } from '@/lib/structured-data'; export default async function Page({ params, @@ -27,16 +28,46 @@ export default async function Page({ // Determine if this is the root page (no sidebar needed) const isRootPage = !slug || slug.length === 0; + // Generate structured data for non-root pages + let structuredData = ''; + if (!isRootPage && slug) { + const slugString = slug.join('/'); + const url = `https://deploystack.io/docs/${slugString}`; + + // Get the final title (same logic as in generateMetadata) + let finalTitle = page.data.title; + try { + const filePath = page.file.path; + const absolutePath = `./docs/${filePath}`; + const rawContent = await readFile(absolutePath, 'utf-8'); + finalTitle = getFinalPageTitle(rawContent, page.data.title); + } catch (error) { + finalTitle = page.data.title; + } + + const articleSchema = generateTechArticleSchema({ + title: finalTitle, + description: page.data.description, + slug, + url, + }); + + const breadcrumbSchema = generateBreadcrumbSchema(slug); + structuredData = combineSchemas(articleSchema, breadcrumbSchema); + } + // Use HomeLayout for root page (no sidebar), DocsLayout for all other pages if (isRootPage) { return ( - -
-
- -
-
-
+ <> + +
+
+ +
+
+
+ ); } @@ -54,23 +85,31 @@ export default async function Page({ } return ( - - - - - - - + <> + {structuredData && ( +