interface JsonLdProps { data: Record; } export function JsonLd({ data }: JsonLdProps) { // Escape `<` so user-controlled titles/descriptions cannot break out of the // ` (JSON.stringify alone does not escape it). const json = JSON.stringify(data).replace(/ ); } const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://belgianbitcoinembassy.org"; export function OrganizationJsonLd({ sameAs }: { sameAs?: string[] } = {}) { const sameAsUrls = sameAs && sameAs.length > 0 ? sameAs : ["https://t.me/belgianbitcoinembassy"]; return ( ); } export function WebSiteJsonLd() { return ( ); } interface BlogPostingJsonLdProps { title: string; description: string; slug: string; publishedAt?: string; authorName?: string; } export function BlogPostingJsonLd({ title, description, slug, publishedAt, authorName, }: BlogPostingJsonLdProps) { return ( ); } interface EventJsonLdProps { name: string; description?: string; startDate: string; endDate?: string; location?: string; url: string; imageUrl?: string; organizerName?: string; organizerUrl?: string; } export function EventJsonLd({ name, description, startDate, endDate, location, url, imageUrl, organizerName, organizerUrl, }: EventJsonLdProps) { const orgName = organizerName || "Belgian Bitcoin Embassy"; const orgUrl = organizerUrl || siteUrl; return ( ); } interface FaqJsonLdProps { items: { question: string; answer: string }[]; } export function FaqPageJsonLd({ items }: FaqJsonLdProps) { if (items.length === 0) return null; return ( ({ "@type": "Question", name: item.question, acceptedAnswer: { "@type": "Answer", text: item.answer, }, })), }} /> ); } interface BreadcrumbItem { name: string; href: string; } export function BreadcrumbJsonLd({ items }: { items: BreadcrumbItem[] }) { return ( ({ "@type": "ListItem", position: index + 1, name: item.name, item: `${siteUrl}${item.href}`, })), }} /> ); }