The problem
The frontmatter mapping takes one field name per canonical field. A repo where a field has a documented fallback cannot be expressed, and either choice produces false positives.
My posts have both title (the H1, written for a human) and an optional seoTitle (short, written for the <title> tag). The site does post.seoTitle ?? post.title. Three of ten posts have no seoTitle because their title is already short enough.
Mapping "title": "title" gives 4 title-length errors, on posts whose real <title> is 37 to 43 characters:
automated-newsroom.es title=87 seoTitle=43
automated-newsroom.en title=78 seoTitle=38
honest-ai-visibility.es title=69 seoTitle=37
agent-fleet.es title=61 seoTitle=43
Mapping "title": "seoTitle" gives 3 missing-title errors instead, on the posts that legitimately do not set it:
{
"rule": "missing-title",
"file": "content/blog/agent-guardrails.en.md",
"message": "mapped title field (seoTitle) is missing or empty",
"severity": "error"
}
Both readings are wrong about the same 7 posts. There is no third option.
Suggested fix
Let a mapped value be an array of field names, first non empty wins:
"frontmatter": {
"title": ["seoTitle", "title"],
"description": "description"
}
A string stays a string, so every existing config keeps working, and null keeps meaning the field is unused. The change is in the resolver in lib/config.mjs, and the rules themselves do not need to know about it. The error message would name the field that actually resolved, or the whole chain when none did.
This is not specific to titles. description with a fallback to an excerpt field, and updatedDate falling back to date, are the same shape. The updatedDate one matters for AEO: a repo that never sets it would get its freshness signal from date instead of dropping the rule entirely.
Related to #1, found in the same run, but independent of it.
The problem
The
frontmattermapping takes one field name per canonical field. A repo where a field has a documented fallback cannot be expressed, and either choice produces false positives.My posts have both
title(the H1, written for a human) and an optionalseoTitle(short, written for the<title>tag). The site doespost.seoTitle ?? post.title. Three of ten posts have noseoTitlebecause theirtitleis already short enough.Mapping
"title": "title"gives 4title-lengtherrors, on posts whose real<title>is 37 to 43 characters:Mapping
"title": "seoTitle"gives 3missing-titleerrors instead, on the posts that legitimately do not set it:{ "rule": "missing-title", "file": "content/blog/agent-guardrails.en.md", "message": "mapped title field (seoTitle) is missing or empty", "severity": "error" }Both readings are wrong about the same 7 posts. There is no third option.
Suggested fix
Let a mapped value be an array of field names, first non empty wins:
A string stays a string, so every existing config keeps working, and
nullkeeps meaning the field is unused. The change is in the resolver inlib/config.mjs, and the rules themselves do not need to know about it. The error message would name the field that actually resolved, or the whole chain when none did.This is not specific to titles.
descriptionwith a fallback to an excerpt field, andupdatedDatefalling back todate, are the same shape. TheupdatedDateone matters for AEO: a repo that never sets it would get its freshness signal fromdateinstead of dropping the rule entirely.Related to #1, found in the same run, but independent of it.