-
-
-
-
-
-
+ // Per-post structured data. The root layout emits site-wide WebSite +
+ // SoftwareApplication nodes; this classifies each post as an Article so a
+ // crawler can model author, publish date, and headline instead of guessing —
+ // the content-quality signal that helps Google prioritize a young blog's URLs
+ // for indexing (and unlocks Article rich results). `image`/`url` must resolve,
+ // so they mirror the OG route and canonical exactly.
+ const canonical = `${siteUrl}/blog/${slug}`;
+ const jsonLd = {
+ '@context': 'https://schema.org',
+ '@type': 'BlogPosting',
+ headline: post.data.title,
+ ...(post.data.description
+ ? { description: post.data.description }
+ : {}),
+ datePublished: post.data.date,
+ dateModified: post.data.date,
+ author: { '@type': 'Person', name: post.data.author },
+ publisher: { '@type': 'Organization', name: appName, url: siteUrl },
+ image: `${siteUrl}/og/blog/${slug}`,
+ mainEntityOfPage: { '@type': 'WebPage', '@id': canonical },
+ url: canonical,
+ ...(post.data.tags?.length
+ ? { keywords: post.data.tags.join(', ') }
+ : {}),
+ inLanguage: 'en-US',
+ };
- {related.length > 0 ? (
-