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
Set two environment variables and a dismissible banner runs across the top of
the whole site. 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 the message are set, and each dismissal
persists per announcement ID in localStorage. What follows covers the link,
the pinned variant, and every variable the bar reads.
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 renders a centered message in the brand color with a close button on the
right. The strip is a role="region" labeled 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 keeps the
close button: 0, no, an empty string, or the variable left unset.
The bar writes each dismissal to 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 decide when the bar shows up:
- 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, as in Safari private browsing or a locked-down browser profile, a failed read still shows the bar and the component ignores a failed write, so the close click hides it for that 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 the build bakes
their values into the client bundle. Changing a banner means a rebuild and a
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. Accepts an internal path or an external URL. 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 bar writes the dismissal flag, 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".