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 page when a published page owns the detail, or an external url when 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 fieldPurpose
idStable, lowercase identifier for the scheduled announcement
starts_at / ends_atInclusive ISO dates that define the visible window
message.en / message.frRequired bilingual announcement copy
link.pageOptional internal content path, resolved in the reader’s language
link.urlOptional external URL; mutually exclusive with link.page
link.label.en / link.label.frRequired 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 or role="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.