Dismissal key. Required with the message to render the bar. Used as the
localStorage suffix, so a new ID re-shows the bar for every reader.
Announcement Bar
A site-wide dismissible announcement bar can be activated by setting environment
variables. app/layout.tsx reads them and mounts the bar above everything else
in the body, so it sits over the sidebar, the header, and the page. The bar
renders only when both the ID and message are set, and dismissals persist per
announcement ID via localStorage.
Quick Start
Enable the bar with an ID and message.
NEXT_PUBLIC_ANNOUNCEMENT_ID=launch
NEXT_PUBLIC_ANNOUNCEMENT_MESSAGE="Welcome to our new docs"That's a centered message in brand color with a close button on the right. The
strip is a role="region" labelled aria-label="Announcement", and the close
button carries aria-label="Dismiss announcement".
Adding Options
Add a link. The link renders only when both the href and label are set — the component's prop types pair them, so half a link is no link.
NEXT_PUBLIC_ANNOUNCEMENT_ID=launch
NEXT_PUBLIC_ANNOUNCEMENT_MESSAGE="Welcome to our new docs"
NEXT_PUBLIC_ANNOUNCEMENT_HREF=/getting-started/introduction
NEXT_PUBLIC_ANNOUNCEMENT_LINK_LABEL="Get started"The link renders inline after the message text, underlined, and drops the underline on hover. An internal path like the one above navigates in place.
Advanced
Pin the bar so readers can't close it, and point it at an external URL. An href
starting with http://, https://, or // opens in a new tab with
rel="noopener noreferrer".
NEXT_PUBLIC_ANNOUNCEMENT_ID=2026-key-rotation
NEXT_PUBLIC_ANNOUNCEMENT_MESSAGE="Rotate your API keys before March 1"
NEXT_PUBLIC_ANNOUNCEMENT_HREF=https://status.example.com/key-rotation
NEXT_PUBLIC_ANNOUNCEMENT_LINK_LABEL="Read the advisory"
NEXT_PUBLIC_ANNOUNCEMENT_DISMISSIBLE=falseOnly the exact string false turns dismissal off. Any other value — 0, no,
an empty string, or the variable left unset — keeps the close button.
Dismissals are stored in localStorage under
owndocs:announcement-dismissed:<id>. Give the next announcement a fresh ID and
the bar comes back for everyone who closed the last one.
Three behaviors are worth knowing before you ship a banner:
- A dismissible bar starts hidden and appears after the first client effect
reads
localStorage. That's what stops an already-dismissed banner from flashing on every page load. A pinned bar (DISMISSIBLE=false) skips the lookup and shows immediately. - When
localStorageis unreachable — Safari private browsing, a locked-down browser profile — the read failure falls back to showing the bar, and the write failure is swallowed so the close click still hides it for the session. - An empty message renders nothing even when the ID is set, so clearing
NEXT_PUBLIC_ANNOUNCEMENT_MESSAGEis enough to take a banner down.
These are NEXT_PUBLIC_* variables read at module scope, so their values are
baked into the client bundle at build time. Changing a banner means a rebuild
and redeploy, not just a server restart.
Options
NEXT_PUBLIC_ANNOUNCEMENT_IDenvNEXT_PUBLIC_ANNOUNCEMENT_MESSAGEenvBanner message. Required with the ID to render the bar; an empty value hides it.
NEXT_PUBLIC_ANNOUNCEMENT_HREFenvOptional link target. Internal paths and external URLs are accepted. An
http://, https://, or // prefix marks it external and adds
target="_blank" with rel="noopener noreferrer".
NEXT_PUBLIC_ANNOUNCEMENT_LINK_LABELenvOptional link text. The link renders only when both the href and label are set.
NEXT_PUBLIC_ANNOUNCEMENT_DISMISSIBLEenvDefault: trueSet to exactly false to hide the close button. Any other value keeps
dismissal on.
localStorage keystringDefault: owndocs:announcement-dismissed:<id>Where the dismissal flag is written, as the string true. Clearing it brings
the bar back for that reader.
landmarkstringDefault: AnnouncementThe bar is a role="region" with aria-label="Announcement"; the close
button uses aria-label="Dismiss announcement".