Every Strand post is an MDX file at content/posts/<slug>.mdx whose YAML frontmatter must satisfy PostFrontmatter (defined in packages/core/schema.ts). A post that does not validate cannot be committed or merged. Write frontmatter to pass on the first try, then self-check with strand validate <slug> or the MCP validate_post tool.
Required vs optional fields
Required: title, slug, description, publishedAt, author.
Defaulted (safe to omit): status (draft), tags ([]), type (BlogPosting), noindex (false), faq ([]), sources ([]).
Optional: updatedAt, canonicalUrl, featureImage, og, summary.
Rules that commonly trip validation
title≤ 70 characters (SEO title length). Write for the SERP, not just the page.description50–160 characters (Bing SEO/GEO hard window is 25–160; authored posts keep the 50-char quality floor). Soft target 120–160 for SERP snippets. Make it a real summary with the primary keyword, not filler.@strand-cms/corealso clamps viametaDescription()at emit time, but authored copy must still validate.slugis kebab-case^[a-z0-9]+(?:-[a-z0-9]+)*$. No spaces, capitals, underscores, or trailing hyphens. It must match the filename.publishedAt/updatedAtare ISO 8601 datetimes.authormust reference an existingcontent/authors/<id>.mdx. Create the author file if the persona is new.featureImage.altis required whenfeatureImageis present (accessibility + image SEO).- The body must not open with an
# H1heading — Strand themes render the frontmattertitleas the page<h1>, so an in-body H1 ships a duplicate. Start the body with the answer-first lede paragraph; use##for sections.
Get the GEO fields right (they are why this project exists)
summary— a ≤280-char TL;DR. It powersspeakableschema and is the snippet AI search engines extract. Lead with the answer.type— useNewsArticlefor time-sensitive news,BlogPostingotherwise. This drives the JSON-LD type.faq— 2–5 genuine question/answer pairs that match how people actually query. Emitted asFAQPageschema and frequently surfaced verbatim by AI search.sources— every external factual claim should map to an entry here (seestrand-fact-check-cite). Cited posts are trusted more by both Google and LLMs.
Example
---
title: "Bulgaria's 2026 EV Charging Grid: What Changed"
slug: bulgaria-2026-ev-charging-grid
description: "A plain-language look at Bulgaria's 2026 EV charging expansion: new fast-charger counts, grid funding, and what it means for drivers."
publishedAt: "2026-06-05T08:00:00Z"
author: maria-petrova
type: NewsArticle
tags: [bulgaria, ev, infrastructure]
summary: "Bulgaria added X fast chargers in 2026 under EU grid funding, concentrated on the A1/A2 corridors; rural coverage still lags."
faq:
- q: "How many public EV chargers does Bulgaria have in 2026?"
a: "Roughly N, up from M in 2025, with most growth on motorway corridors."
sources:
- title: "Ministry of Energy 2026 infrastructure report"
url: "https://example.gov.bg/report-2026"
publisher: "Ministry of Energy"
---
After writing frontmatter, always run validation and fix any reported field before handing off to strand-publish.