This repository has no description
Something went wrong. Try again.
2.0 kB · 71 lines
TSX
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172import type { Post, Media, Tag } from '@/payload-types'
interface ArticleSchemaProps { post: Post url: string}
export function ArticleSchema({ post, url }: ArticleSchemaProps) { const { title, publishDate, updatedDate, excerpt, tags = [], seo, subtitle } = post
// Resolve tag slugs — tags may be populated objects or just IDs const tagSlugs: string[] = (tags ?? []) .map((t) => (typeof t === 'object' && t !== null ? (t as Tag).name ?? '' : '')) .filter(Boolean)
const articleSchema: Record<string, unknown> = { '@context': 'https://schema.org', '@type': 'Article', headline: seo?.title ?? title, name: seo?.title ?? title, description: seo?.description ?? excerpt ?? subtitle, datePublished: publishDate, dateModified: updatedDate ?? publishDate, url, mainEntityOfPage: { '@type': 'WebPage', '@id': url, }, author: { '@type': 'Person', name: 'Chris Arter', url: 'https://arter.dev', sameAs: [ 'https://github.com/christopherarter', 'https://bsky.app/profile/arter.dev', 'https://www.linkedin.com/in/chrisarter1/', ], }, publisher: { '@type': 'Person', name: 'Chris Arter', url: 'https://arter.dev', image: { '@type': 'ImageObject', url: 'https://arter.dev/images/chris-arter.jpg', }, }, articleSection: tagSlugs.length > 0 ? tagSlugs[0] : 'Technology', keywords: tagSlugs.join(', '), }
// Add image if available from SEO const seoImage = seo?.image if (seoImage && typeof seoImage === 'object') { const img = seoImage as Media if (img.url) { articleSchema['image'] = { '@type': 'ImageObject', url: img.url.startsWith('http') ? img.url : `https://arter.dev${img.url}`, alt: img.alt ?? title, } } }
return ( <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema, null, 2) }} /> )}