Skip to content

Per-page announcements (additive follow-up to the site-wide banner) #403

Description

@mmcky

Background

The dismissible announcement banner shipped as site-wide only — a single announcement (plus optional announcement_expires) theme option rendered at the top of every page. See the Announcement Banner docs.

The renderer was deliberately built to be additive: the template loops over a list of notices, announcement.js evaluates each .qe-announcement row independently (its own content-hash dismissal + its own expiry), and the dismissed-set in localStorage already tracks multiple IDs. So the JS, persistence, and most of the CSS already support N rows. What's left for per-page is the config plumbing, a little stacking polish, and one design decision.

Goal

Let an individual page carry its own announcement that stacks additively with the global one: global on top, page-specific below. Example use case — flagging that a single lecture now uses a newer library version (pandas==3.0) while a site-wide notice (an Anaconda upgrade) stays visible.

Open decision: how should a per-page notice be authored?

Mechanism Pros Cons
Config keyed by docname (an announcements: map in html_theme_options) Everything in one place; easy to audit and remove stale notices; non-authors can add one without touching lecture files Becomes public theme-option API (hard to change later); brittle to page renames; page content lives far from the page
MyST frontmatter on the page Co-located with the content; survives renames; natural fit for "this lecture uses …" Spread across many files; harder to get a site-wide overview

My current lean is to re-evaluate frontmatter for per-page, since page-specific content arguably belongs with the page — but this is the thing to settle before building.

Settled design (for whichever mechanism wins)

  • Additive: when both global and per-page are present, render two stacked rows (global first).
  • Each row independent: its own expiry, its own × dismiss, its own content-hash so editing one re-shows only that one.
  • When a page has only one of the two, show just that one; when all rows are dismissed/expired, the bar collapses.

Scope / priority

Demand-driven — open this when there's a concrete need. The site-wide banner already covers the primary case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions