163 lines
4.1 KiB
TypeScript
163 lines
4.1 KiB
TypeScript
import { ITopic } from '@/models/topic'
|
|
|
|
interface ArticleStructuredData {
|
|
title: string
|
|
description: string
|
|
image: string
|
|
publishedTime: string
|
|
authorName: string
|
|
url: string
|
|
readingTime?: string
|
|
tags?: string[]
|
|
}
|
|
|
|
export function generateArticleStructuredData({
|
|
title,
|
|
description,
|
|
image,
|
|
publishedTime,
|
|
authorName,
|
|
url,
|
|
readingTime,
|
|
tags = [],
|
|
}: ArticleStructuredData): string {
|
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://siliconpin.com'
|
|
|
|
const structuredData = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Article',
|
|
headline: title,
|
|
description: description,
|
|
image: {
|
|
'@type': 'ImageObject',
|
|
url: image.startsWith('http') ? image : `${baseUrl}${image}`,
|
|
width: 800,
|
|
height: 450,
|
|
},
|
|
author: {
|
|
'@type': 'Person',
|
|
name: authorName,
|
|
},
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: 'SiliconPin',
|
|
logo: {
|
|
'@type': 'ImageObject',
|
|
url: `${baseUrl}/favicon.ico`,
|
|
width: 32,
|
|
height: 32,
|
|
},
|
|
},
|
|
datePublished: publishedTime,
|
|
dateModified: publishedTime,
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': `${baseUrl}${url}`,
|
|
},
|
|
url: `${baseUrl}${url}`,
|
|
...(readingTime && {
|
|
timeRequired: readingTime,
|
|
}),
|
|
...(tags.length > 0 && {
|
|
keywords: tags.join(', '),
|
|
about: tags.map(tag => ({
|
|
'@type': 'Thing',
|
|
name: tag,
|
|
})),
|
|
}),
|
|
}
|
|
|
|
return JSON.stringify(structuredData, null, 2)
|
|
}
|
|
|
|
export function generateTopicListingStructuredData(topics: ITopic[]): string {
|
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://siliconpin.com'
|
|
|
|
const structuredData = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Topic',
|
|
name: 'SiliconPin Topics',
|
|
description: 'Technical articles, tutorials, and insights from the SiliconPin community',
|
|
url: `${baseUrl}/topics`,
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: 'SiliconPin',
|
|
logo: {
|
|
'@type': 'ImageObject',
|
|
url: `${baseUrl}/favicon.ico`,
|
|
width: 32,
|
|
height: 32,
|
|
},
|
|
},
|
|
topicPost: topics.slice(0, 10).map(topic => ({
|
|
'@type': 'TopicPosting',
|
|
headline: topic.title,
|
|
description: topic.excerpt,
|
|
url: `${baseUrl}/topics/${topic.slug}`,
|
|
datePublished: new Date(topic.publishedAt).toISOString(),
|
|
author: {
|
|
'@type': 'Person',
|
|
name: topic.author,
|
|
},
|
|
image: {
|
|
'@type': 'ImageObject',
|
|
url: topic.coverImage.startsWith('http') ? topic.coverImage : `${baseUrl}${topic.coverImage}`,
|
|
width: 800,
|
|
height: 450,
|
|
},
|
|
keywords: topic.tags.map(tag => tag.name).join(', '),
|
|
})),
|
|
}
|
|
|
|
return JSON.stringify(structuredData, null, 2)
|
|
}
|
|
|
|
export function generateWebsiteStructuredData(): string {
|
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://siliconpin.com'
|
|
|
|
const structuredData = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebSite',
|
|
name: 'SiliconPin',
|
|
description: 'Modern web hosting and cloud solutions with integrated topic platform',
|
|
url: baseUrl,
|
|
potentialAction: {
|
|
'@type': 'SearchAction',
|
|
target: {
|
|
'@type': 'EntryPoint',
|
|
urlTemplate: `${baseUrl}/search?q={search_term_string}`,
|
|
},
|
|
'query-input': 'required name=search_term_string',
|
|
},
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: 'SiliconPin',
|
|
logo: {
|
|
'@type': 'ImageObject',
|
|
url: `${baseUrl}/favicon.ico`,
|
|
width: 32,
|
|
height: 32,
|
|
},
|
|
},
|
|
}
|
|
|
|
return JSON.stringify(structuredData, null, 2)
|
|
}
|
|
|
|
export function generateBreadcrumbStructuredData(items: Array<{ name: string; url: string }>): string {
|
|
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://siliconpin.com'
|
|
|
|
const structuredData = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'BreadcrumbList',
|
|
itemListElement: items.map((item, index) => ({
|
|
'@type': 'ListItem',
|
|
position: index + 1,
|
|
name: item.name,
|
|
item: item.url.startsWith('http') ? item.url : `${baseUrl}${item.url}`,
|
|
})),
|
|
}
|
|
|
|
return JSON.stringify(structuredData, null, 2)
|
|
}
|