initial commit
This commit is contained in:
162
lib/structured-data.ts
Normal file
162
lib/structured-data.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user