--- import BaseLayout from './BaseLayout.astro'; import BlogTagChip from '../components/BlogTagChip.astro'; import type { BlogTag } from '../lib/blog-tags'; import GiscusComments from '../components/GiscusComments.astro'; import FaqAccordion from '../components/blog/FaqAccordion.astro'; interface FaqEntry { q: string; a: string; } interface Props { title: string; description: string; pubDate: Date; updatedDate?: Date; author: string; tags?: BlogTag[]; heroImage?: string; /** Optional FAQ from the post frontmatter: rendered after the body and emitted as FAQPage schema. */ faq?: FaqEntry[]; } const { title, description, pubDate, updatedDate, author, tags = [], heroImage, faq = [] } = Astro.props; const formattedDate = pubDate.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); const formattedUpdatedDate = updatedDate?.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric', }); /** Served from the site: an avatar fetched from GitHub would report every reader to them. */ const AUTHOR_AVATAR_URL = '/iptvnator/author-4gray.jpg'; const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString(); const blogPostSchema = { '@context': 'https://schema.org', '@type': 'BlogPosting', headline: title, description, datePublished: pubDate.toISOString(), dateModified: (updatedDate ?? pubDate).toISOString(), author: { '@type': 'Person', name: author, url: 'https://github.com/4gray', }, publisher: { '@type': 'Organization', name: 'IPTVnator', url: 'https://4gray.github.io/iptvnator/', logo: { '@type': 'ImageObject', url: 'https://4gray.github.io/iptvnator/favicon-256x256.png', }, }, mainEntityOfPage: canonicalURL, image: heroImage ? new URL(heroImage, Astro.site).toString() : undefined, }; const faqSchema = faq.length > 0 ? { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((entry) => ({ '@type': 'Question', name: entry.q, acceptedAnswer: { '@type': 'Answer', text: entry.a }, })), } : null; const jsonLd = faqSchema ? [blogPostSchema, faqSchema] : blogPostSchema; ---
Back to blog
{ tags.length > 0 && ( <> · {tags.map((tag) => ( ))} ) }

{title}

{description}

{`${author}
{author}
{ updatedDate && (
Updated {formattedUpdatedDate}
) }

{heroImage && (
)}
{faq.length > 0 && (

FAQ

Frequently asked questions

)}