Announcement
An announcement is a full-width banner above the site header carrying one short, time-limited site-wide message. It is data-driven: no active record in data/announcements.yml means no banner renders. The same data file may carry separate schedules for the main and brand sites.
Scope#
A scheduled record belongs to one site, rather than to its home page. The shared base layout renders the active record on every page of that site, so a person arriving directly on an article or reference receives the same timely notice. Put a main-site record under main and a brand-only record under brand; do not duplicate an announcement in individual pages.
Example#
When to use#
- One short, time-limited message that matters site-wide: a release, an event, a promotion
- Top of page only, above the header — never inline within content
- Remove it when the news expires; a permanent banner is navigation, not an announcement
- Use an internal content
pagewhen a published page owns the detail, or an externalurlwhen the destination is outside these sites; each record accepts exactly one
Implementation#
brand:
- id: brand-preview
starts_at: 2026-08-19
ends_at: 2026-09-02
message:
en: "The brand documentation is currently being refined."
fr: "La documentation de marque est en cours de mise au point."
link:
label:
en: "Read the component documentation"
fr: "Lire la documentation du composant"
page: /docs/site-implementation/components/announcement/For an external destination, replace page: with url:. Do not set both.
<aside class="announcement" aria-label="Announcement" data-announcement-id="brand-preview">
<div class="announcement-inner">
<p class="announcement-copy">The brand documentation is currently being refined.</p>
<a class="announcement-link" href="/en/docs/site-implementation/components/announcement/">Read the component documentation</a>
</div>
</aside>layouts/partials/announcement.html selects records for the current site, renders one only while starts_at through ends_at includes the build time, and fails the build if schedules overlap. It resolves link.page through the current language; link.url renders as an external link with rel="noopener noreferrer". scripts/check-announcements.mjs validates bilingual copy, dates, unique ids, one destination type, and non-overlapping schedules before the Hugo build. The component uses generated component.announcement.* tokens for its surface, signal border, link, and spacing.
Options#
| Data field | Purpose |
|---|---|
id | Stable, lowercase identifier for the scheduled announcement |
starts_at / ends_at | Inclusive ISO dates that define the visible window |
message.en / message.fr | Required bilingual announcement copy |
link.page | Optional internal content path, resolved in the reader’s language |
link.url | Optional external URL; mutually exclusive with link.page |
link.label.en / link.label.fr | Required bilingual label whenever a link exists |
Interface manifest
- Kind
- Component
- Category
- Content
- Status
- Implemented
- Implementation
- Partial:
layouts/partials/announcement.htmlLayout:layouts/_default/baseof.htmlData:data/announcements.ymlCSS:assets/css/site.cssi18n:announcementConfiguration:tokens/core.tokens.json
Accessibility#
- The skip link stays the first focusable element. The static announcement follows it, before the header, so keyboard users can still bypass repeated site chrome immediately.
- The banner is a named
<aside>, not a live region orrole="alert": its content is available on initial page load and should not interrupt a reader. - The content includes meaningful text. There is no icon-only or colour-only state.
- Its optional destination is an ordinary link. External links open in a new tab with the appropriate relationship; internal links remain same-tab navigation.
- Validation and the partial both ensure no more than one record can be active for a site. Stacked banners would multiply the repeated content every reader crosses.