From 52649dfb3b0108a922adf19f69d89e30dd69f74e Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Thu, 1 Jan 2026 18:39:39 +0700 Subject: [PATCH] feat(docs): add SEO metadata to all documentation pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create centralized SEO config (docs-seo.ts) with DOCS_PAGES constants and createDocsMetadata helper for DRY metadata generation - Add JSON-LD schema helpers (docs-schema.ts) for BreadcrumbList, TechArticle, HowTo, and WebAPI structured data - Create JsonLd component for rendering structured data - Add metadata exports and JSON-LD to all 10 docs pages: - Getting Started, Generation, Images, Live URLs, Authentication - API Overview, Generations API, Images API, Flows API, Live Scopes API 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../src/app/(apps)/docs/api/flows/page.tsx | 23 +++- .../app/(apps)/docs/api/generations/page.tsx | 23 +++- .../src/app/(apps)/docs/api/images/page.tsx | 23 +++- .../app/(apps)/docs/api/live-scopes/page.tsx | 24 +++- apps/landing/src/app/(apps)/docs/api/page.tsx | 23 +++- .../app/(apps)/docs/authentication/page.tsx | 22 +++- .../src/app/(apps)/docs/generation/page.tsx | 23 +++- .../src/app/(apps)/docs/images/page.tsx | 22 +++- .../src/app/(apps)/docs/live-urls/page.tsx | 23 +++- apps/landing/src/app/(apps)/docs/page.tsx | 22 +++- apps/landing/src/components/seo/JsonLd.tsx | 7 ++ apps/landing/src/config/docs-schema.ts | 74 +++++++++++ apps/landing/src/config/docs-seo.ts | 119 ++++++++++++++++++ 13 files changed, 415 insertions(+), 13 deletions(-) create mode 100644 apps/landing/src/components/seo/JsonLd.tsx create mode 100644 apps/landing/src/config/docs-schema.ts create mode 100644 apps/landing/src/config/docs-seo.ts diff --git a/apps/landing/src/app/(apps)/docs/api/flows/page.tsx b/apps/landing/src/app/(apps)/docs/api/flows/page.tsx index 314fd21..a0af1a9 100644 --- a/apps/landing/src/app/(apps)/docs/api/flows/page.tsx +++ b/apps/landing/src/app/(apps)/docs/api/flows/page.tsx @@ -1,7 +1,11 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -10,6 +14,19 @@ import { ResponseBlock, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['api-flows']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'API Reference', path: '/docs/api/' }, + { name: 'Flows', path: '/docs/api/flows/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, { id: 'list-flows', text: 'List Flows', level: 2 }, @@ -25,7 +42,10 @@ const tocItems = [ export default function FlowsAPIPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/api/generations/page.tsx b/apps/landing/src/app/(apps)/docs/api/generations/page.tsx index 8412112..5299d35 100644 --- a/apps/landing/src/app/(apps)/docs/api/generations/page.tsx +++ b/apps/landing/src/app/(apps)/docs/api/generations/page.tsx @@ -1,7 +1,11 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -10,6 +14,19 @@ import { ResponseBlock, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['api-generations']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'API Reference', path: '/docs/api/' }, + { name: 'Generations', path: '/docs/api/generations/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'create-generation', text: 'Create Generation', level: 2 }, { id: 'list-generations', text: 'List Generations', level: 2 }, @@ -22,7 +39,10 @@ const tocItems = [ export default function GenerationsAPIPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/api/images/page.tsx b/apps/landing/src/app/(apps)/docs/api/images/page.tsx index 9ed8d21..81f0d0a 100644 --- a/apps/landing/src/app/(apps)/docs/api/images/page.tsx +++ b/apps/landing/src/app/(apps)/docs/api/images/page.tsx @@ -1,7 +1,11 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -10,6 +14,19 @@ import { ResponseBlock, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['api-images']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'API Reference', path: '/docs/api/' }, + { name: 'Images', path: '/docs/api/images/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'upload-image', text: 'Upload Image', level: 2 }, { id: 'list-images', text: 'List Images', level: 2 }, @@ -23,7 +40,10 @@ const tocItems = [ export default function ImagesAPIPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/api/live-scopes/page.tsx b/apps/landing/src/app/(apps)/docs/api/live-scopes/page.tsx index 1b4b6f3..a0e4a97 100644 --- a/apps/landing/src/app/(apps)/docs/api/live-scopes/page.tsx +++ b/apps/landing/src/app/(apps)/docs/api/live-scopes/page.tsx @@ -1,8 +1,11 @@ - +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -11,6 +14,19 @@ import { ResponseBlock, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['api-live-scopes']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'API Reference', path: '/docs/api/' }, + { name: 'Live Scopes', path: '/docs/api/live-scopes/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'overview', text: 'Overview', level: 2 }, { id: 'create-scope', text: 'Create Scope', level: 2 }, @@ -25,7 +41,10 @@ const tocItems = [ export default function LiveScopesAPIPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/api/page.tsx b/apps/landing/src/app/(apps)/docs/api/page.tsx index 7bcbdf2..dc7bbe1 100644 --- a/apps/landing/src/app/(apps)/docs/api/page.tsx +++ b/apps/landing/src/app/(apps)/docs/api/page.tsx @@ -1,7 +1,11 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema, API_REFERENCE_SCHEMA } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -10,6 +14,18 @@ import { LinkCardGrid, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['api-overview']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'API Reference', path: '/docs/api/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'base-url', text: 'Base URL', level: 2 }, { id: 'authentication', text: 'Authentication', level: 2 }, @@ -22,7 +38,11 @@ const tocItems = [ export default function APIOverviewPage() { return ( - + + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/authentication/page.tsx b/apps/landing/src/app/(apps)/docs/authentication/page.tsx index 43d547b..4356ed5 100644 --- a/apps/landing/src/app/(apps)/docs/authentication/page.tsx +++ b/apps/landing/src/app/(apps)/docs/authentication/page.tsx @@ -1,13 +1,29 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, InlineCode, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['authentication']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'Authentication', path: '/docs/authentication/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'early-access', text: 'Early Access', level: 2 }, { id: 'using-your-api-key', text: 'Using Your API Key', level: 2 }, @@ -17,7 +33,10 @@ const tocItems = [ export default function AuthenticationPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/generation/page.tsx b/apps/landing/src/app/(apps)/docs/generation/page.tsx index 9b25899..0315f67 100644 --- a/apps/landing/src/app/(apps)/docs/generation/page.tsx +++ b/apps/landing/src/app/(apps)/docs/generation/page.tsx @@ -1,8 +1,11 @@ - +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -10,6 +13,18 @@ import { ResponseBlock, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['generation']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'Image Generation', path: '/docs/generation/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'basic-generation', text: 'Basic Generation', level: 2 }, { id: 'aspect-ratios', text: 'Aspect Ratios', level: 2 }, @@ -22,7 +37,10 @@ const tocItems = [ export default function GenerationPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/images/page.tsx b/apps/landing/src/app/(apps)/docs/images/page.tsx index 6a03177..d1424f5 100644 --- a/apps/landing/src/app/(apps)/docs/images/page.tsx +++ b/apps/landing/src/app/(apps)/docs/images/page.tsx @@ -1,6 +1,10 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -8,6 +12,18 @@ import { ResponseBlock, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['images']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'Working with Images', path: '/docs/images/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'image-urls', text: 'Image URLs', level: 2 }, { id: 'uploading-images', text: 'Uploading Images', level: 2 }, @@ -19,7 +35,10 @@ const tocItems = [ export default function ImagesPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/live-urls/page.tsx b/apps/landing/src/app/(apps)/docs/live-urls/page.tsx index 62bf04f..ee68036 100644 --- a/apps/landing/src/app/(apps)/docs/live-urls/page.tsx +++ b/apps/landing/src/app/(apps)/docs/live-urls/page.tsx @@ -1,14 +1,29 @@ - +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { Table } from '@/components/docs/shared/Table'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema } from '@/config/docs-schema'; import { Hero, SectionHeader, InlineCode, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['live-urls']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, + { name: 'Live URLs', path: '/docs/live-urls/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'the-concept', text: 'The Concept', level: 2 }, { id: 'url-format', text: 'URL Format', level: 2 }, @@ -22,7 +37,10 @@ const tocItems = [ export default function LiveUrlsPage() { return ( - + + + + ); } diff --git a/apps/landing/src/app/(apps)/docs/page.tsx b/apps/landing/src/app/(apps)/docs/page.tsx index 33f8168..6331ab6 100644 --- a/apps/landing/src/app/(apps)/docs/page.tsx +++ b/apps/landing/src/app/(apps)/docs/page.tsx @@ -1,6 +1,10 @@ +import type { Metadata } from 'next'; import { TipBox } from '@/components/docs/shared/TipBox'; import { CodeBlock } from '@/components/docs/shared/CodeBlock'; import { DocPage } from '@/components/docs/layout/DocPage'; +import { JsonLd } from '@/components/seo/JsonLd'; +import { createDocsMetadata, DOCS_PAGES } from '@/config/docs-seo'; +import { createBreadcrumbSchema, createTechArticleSchema, HOW_TO_SCHEMA } from '@/config/docs-schema'; import { Hero, SectionHeader, @@ -9,6 +13,17 @@ import { LinkCardGrid, } from '@/components/docs/blocks'; +const PAGE = DOCS_PAGES['getting-started']; + +export const metadata: Metadata = createDocsMetadata(PAGE); + +const breadcrumbSchema = createBreadcrumbSchema([ + { name: 'Home', path: '/' }, + { name: 'Documentation', path: '/docs/' }, +]); + +const articleSchema = createTechArticleSchema(PAGE); + const tocItems = [ { id: 'what-is-banatie', text: 'What is Banatie?', level: 2 }, { id: 'your-first-image', text: 'Your First Image', level: 2 }, @@ -20,7 +35,11 @@ const tocItems = [ export default function GettingStartedPage() { return ( - + + + + + ); } diff --git a/apps/landing/src/components/seo/JsonLd.tsx b/apps/landing/src/components/seo/JsonLd.tsx new file mode 100644 index 0000000..140ad69 --- /dev/null +++ b/apps/landing/src/components/seo/JsonLd.tsx @@ -0,0 +1,7 @@ +type JsonLdProps = { + data: Record; +}; + +export const JsonLd = ({ data }: JsonLdProps) => ( +