docs/lessons/*.md files are rendered on krillswarm.com via docs/_layouts/lesson.html
and are indexed by search engines. The layout already supported page.title and
page.description front matter, but only 1 of 323 lesson files declared a title
and none declared a description or tags. Every other page fell back to the
filename for its <title> and to the raw page content (headings concatenated
straight into body text, then truncated to 160 characters) for its meta
description — a search result snippet that reads like “SymptomAn INPUT
Server.Pin whose hardware GPIO line was HIGH rendered…”.
docs/lessons/README.md’s required-sections schema never included SEO fields,
so every dev-agent PR since the lessons directory was introduced wrote
issue/pr/date/module/category and stopped there. The layout’s
fallback behavior masked the gap — pages still rendered a plausible-looking
<title> and <meta description>, so nothing looked broken during manual
review.
docs/lessons/README.md — documented title, description, and tags
as required front matter fields, with guidance on what makes a good
meta description for this content (symptom, not fix; under ~155 chars).docs/_layouts/lesson.html — added a <meta name="keywords"> tag driven
by page.tags (additive; title/description rendering was already
wired up, it just had nothing to read).title, description, and tags into all 323 existing
docs/lessons/*.md files. Titles are humanized from the filename slug
(or the file’s own # H1 when present); descriptions are extracted from
each file’s ## Symptom / ## What happened section, stripped of
markdown and truncated to a word boundary under 155 characters; tags
combine the existing module/category values with keywords pulled
from the slug.server/src/jvmTest/.../DocsSeoTest.kt — added
every lesson declares title, description and tags for SEO, mirroring
the existing per-post description: guard.The new DocsSeoTest case fails any future docs/lessons/*.md PR that
omits title, description, or tags — the same mechanism that already
guards docs/_posts/*.md. docs/lessons/README.md’s schema block now
lists the three fields alongside the existing required ones, so a dev
agent copying the template gets them for free.