id | string | Keys, analytics (optional on public pages) |
slug | string | URL segment at {blogPath}/[slug] |
title | string | <h1>, cards, Open Graph fallback |
description | string | Meta description fallback, card excerpt |
excerpt | string? | Prefer over description for card blurbs |
content | { format: "markdown"; html: string; markdown: string } | Render content.html on the article page; serve content.markdown at {blogPath}/[slug].md |
coverImage | string? | Hero image, OG/Twitter image fallback |
publishedAt | string? | Byline, JSON-LD datePublished, OG publishedTime |
updatedAt | string? | JSON-LD dateModified, OG modifiedTime |
readingTime | number? | Minutes to read (round up, minimum 1) |
tags | string[]? | Topic chips on the article page |
clusterRelation | "pillar" | "supporting"? | Optional badge (pillar vs supporting) |
primaryKeyword | string? | Optional chip or metadata |
primaryCluster | { id, slug, name, pillarKeyword }? | Link to {blogPath}/topic/{slug} |
faq | FAQPage? | The article’s FAQ as schema.org JSON-LD. Render it as a visible FAQ block and emit it in a <script type="application/ld+json">. It is not part of content — an article page that ignores this field simply has no FAQ |
seo.title | string? | <title> and OG title |
seo.description | string? | Meta description |
seo.canonicalUrl | string? | Canonical link (absolute or site-relative) |
seo.ogImage | string? | Prefer over coverImage for social cards |
seo.keywords | string[]? | Meta keywords, JSON-LD keywords |
seo.noIndex | boolean? | Set robots: { index: false, follow: false } |