On every `template: upgrade` page the last-edit date rendered twice in
the header region: once in the hero (with a partial-width `border-t`
rule above it) and again ~150px below in `FileContributors`. The two
lines even used different translation keys for the same string
(`common:page-last-updated` vs `page-last-update`).
The collision is a regression from 49d6425, which made the compact
`FileContributors` unconditional at the top of the article. It was
previously gated on `asidePosition === "right-top"`, and the default
`left-bottom` put contributors at the bottom of the page — so the hero
timestamp used to be the only date in the header.
Drops `showLastUpdatedInHero` rather than suppressing the lower line, so
upgrade pages surface freshness the same way every other content page
does. The flag had a single consumer, so the config field and the dead
branch in `TopicLayout` go with it.
Fixes #19025
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Description
Fixes #19025.
On every
template: upgradepage the last-edit date renders twice in the header region: once in the hero, preceded by a partial-widthborder-trule that stops mid-page, and again about 150px below inFileContributors. The two lines even use different translation keys for the same string (common:page-last-updatedin the hero,page-last-updateinFileContributors).On https://ethereum.org/roadmap/glamsterdam/ that reads, top to bottom: h1 → description → stray 768px rule → "Page last updated: July 20, 2026" → hero's full-width bottom border → "Page last update: July 20, 2026" → contributor avatars.
Why it started
The collision is a regression from 49d6425 (migrate/refactor(ui): ContentLayout, TableOfContents), which made the compact
FileContributorsunconditional at the top of the article. It was previously gated onasidePosition === "right-top", and the defaultleft-bottomplaced contributors at the bottom of the page — so the hero timestamp used to be the only date in the header.The hero rule itself is older, carried verbatim from
src/layouts/md/Upgrade.tsxinto theshowLastUpdatedInHeroflag in cba15c3. In the old design the hero held a bulletedsummaryPointslist, so the rule read as a footer under a block of bullets. Pages with a one-linedescription(Glamsterdam, Dencun) leave it floating under a single sentence.Approach
Drop
showLastUpdatedInHerorather than suppressing the lower line, so upgrade pages surface freshness the same way every other content page on the site does. The flag had exactly one consumer, so the config field and the now-dead branch inTopicLayoutgo with it.The
baseDescription→heroDescriptionrename is just the collapse of the two-step derivation back into one; the expression is byte-identical.Affected pages
All
template: upgradepages, in every locale:/roadmap/beacon-chain/,/roadmap/dencun/,/roadmap/fusaka/,/roadmap/glamsterdam/,/roadmap/merge/,/roadmap/pectra/.Testing
Driven locally with a headless browser against
next dev:/roadmap/glamsterdam/— hero description block now contains only the description<p>;.border-t.pt-4.italiccount is0(was1)/roadmap/beacon-chain/—summaryPointsstill render as the<ul>in the hero, no stray rule/staking/and/roadmap/— non-upgrade topics unchanged, no stray rule, no console errorsOne thing I could not verify locally: that the remaining
FileContributorsdate still renders.next devleaveslastEditLocaleTimestampempty (no git-history lookup), so neither date appears locally. It is already rendering on production today and this PR touches nothing in that path — but worth a glance on the deploy preview.tsc --noEmit,eslintandprettier --checkall clean on the changed files.🤖 Generated with Claude Code