@@ -70,12 +70,13 @@ brackets and cost a normalizing ternary on every render; it was removed.
7070 none.
7171- ** ` getBreadcrumbSchema ` requires a _ visible_ breadcrumb nav — it is not a free win.** Emitting a
7272 ` BreadcrumbList ` on a page with no on-screen breadcrumb is markup and schema disagreeing, which is
73- the one thing structured data must never do. The builder ships unused ** on purpose** : it is the
74- schema counterpart to the ` src/components/ui/breadcrumb/ ` primitive, the same way the other 43
75- primitives ship unused. Build the nav first, then pass the node — don't reach for the builder
76- because it happens to exist. (A dead export with no counterpart is a different matter: an unused
77- helper that sits long enough starts getting cited in other files' docs as though it were part of
78- the pattern, and then it is load-bearing fiction. Delete those.)
73+ the one thing structured data must never do. It is ** now used** : blog posts pair a ` BlogPosting `
74+ with a visible breadcrumb nav (built on the ` src/components/ui/breadcrumb/ ` primitive — one of the
75+ 39 primitives this template ships), so the schema and the on-screen trail agree. That is the bar
76+ for any new page — build the nav first, then pass the node; don't reach for the builder because it
77+ happens to exist. (A dead export with no counterpart is a different matter: an unused helper that
78+ sits long enough starts getting cited in other files' docs as though it were part of the pattern,
79+ and then it is load-bearing fiction. Delete those.)
7980- Validate output in Google's Rich Results Test before shipping a new schema type.
8081
8182## Crawlability & indexation
@@ -94,20 +95,20 @@ brackets and cost a normalizing ternary on every render; it was removed.
9495 hreflang is only meaningful with 2+ locales. Re-adding i18n means re-adding per-locale alternates +
9596 ` x-default ` in ` BaseHead ` (git history has the old block).
9697
97- ## Content pages (blog) — wire these when the blog route lands
98+ ## Content pages (blog) — shipped with the live blog route
9899
99- The ` blog ` + ` authors ` collections and ` @astrojs/mdx ` are wired, but ** no ` /blog/ ` route ships** —
100- a stated decision, not an oversight, and the README says so in the same words so the two can't
101- drift. Every project wants its blog shaped differently; the collections are the starting point.
102- When the route lands, these three come with it (** deliberately not built** until then — YAGNI):
100+ The ` /blog/ ` route is ** live** (` src/pages/blog/index.astro ` + ` [slug].astro ` ) over the ` blog ` +
101+ ` authors ` collections and ` @astrojs/mdx ` . The three pieces that ride with a content route are built:
103102
104- - ** RSS** : add a dependency-free endpoint (` src/pages/rss.xml.ts ` ) that maps the ` blog ` collection
105- to escaped RSS 2.0 — hand-rolled, like everything else in ` head ` . Link it from ` BaseHead ` ,
106- ` llms.txt ` , and the footer.
107- - ** Article schema + ` article ` prop** on the post page (pattern above).
108- - ** ` heroImage ` ** is optional in the schema today; make it ** required** for a real blog so every post
109- has an OG image, and add ` og:image:width/height ` from the bundled ` ImageMetadata ` (BaseHead already
110- emits real dims when you pass an ` image ` ).
103+ - ** RSS** : a dependency-free endpoint (` src/pages/rss.xml.ts ` ) maps the ` blog ` collection to escaped
104+ RSS 2.0 via the ` @js/rss ` renderer — hand-rolled like everything else in ` head ` (no ` @astrojs/rss ` ),
105+ self-checked by ` src/js/rss.test.ts ` . Linked from ` BaseHead ` , ` llms.txt ` , and the footer.
106+ - ** Article schema + ` article ` prop** on the post page (` [slug].astro ` ): ` getArticleSchema ` emits a
107+ ` BlogPosting ` with a stable ` @id ` (` ${url}#article ` ), a ` publisher ` reference to the site
108+ Organization, and ` author.url ` (from the author's ` authorLink ` ). ` dateModified ` is emitted ** only**
109+ when the post has an ` updatedDate ` — never invented from ` datePublished ` .
110+ - ** ` heroImage ` is required** on blog posts (` content.config.ts ` — ` image() ` , not ` .optional() ` ), so
111+ every post has an OG image; ` BaseHead ` emits ` og:image:width/height ` from the bundled ` ImageMetadata ` .
111112
112113## Images & Core Web Vitals
113114
0 commit comments