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) }