Raise the breaking-news banner from the article that is breaking - #227
Merged
Conversation
Any editor could already tick "Breaking news" on their article, and the flag did nothing: it was stored, returned by the API, and read by no one. The banner it should have driven was a separate admin-only setting with hand-typed text, so raising one meant messaging an admin and having them retype the headline. Wire the flag to the banner, and derive the banner rather than storing a second copy of the decision. GetBreakingNewsState resolves it on read from the newest published article flagged breaking, falling back to the manual banner when there is none. Deriving it is what makes scheduling work. The published predicate is the same one every other public read uses, so a story scheduled for 11am starts driving the banner at the instant it starts being readable -- there is no publish hook that could fire early, late, or not at all, and unticking the flag takes the banner down just as directly. The public cache is 60s and the scheduler ticks at 60s, so the banner lands within a tick of the story. An article wins over the manual banner: it is the more specific and more recent signal, and "this story is the breaking story now" is the flow the flag exists for. The manual banner is kept separate in the API response so Settings can still edit it while an article overrides it -- binding the form to the effective value would overwrite an admin's text with a headline on their next save. The banner carries the article's slug, not a path: the public site owns its URL shape and already composes links this way for developing stories. Admins can also set a limit after which a flagged article stops holding the homepage. It is off by default, so nothing takes a banner down on an editor's behalf unless someone asked for that. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ES8gPZxe6sb5xSLrBZ7AGk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Any editor could already tick Breaking news on their article, and the flag did nothing — it was stored, returned by the API, and read by no one. The banner it should have driven was a separate admin-only setting with hand-typed text, so raising one meant messaging an admin and having them retype the headline.
This wires the flag to the banner, and derives the banner rather than storing a second copy of the decision.
How it resolves
GetBreakingNewsStateresolves on read from the newest published article flagged breaking, falling back to the manual banner when there is none:Deriving it is what makes scheduling work. That published predicate is the same one every other public read uses, so a story scheduled for 11am starts driving the banner at the instant it starts being readable. There is no publish hook that could fire early, late, or not at all, and unticking the flag takes the banner down just as directly. The public cache is 60s and the scheduler ticks at 60s, so the banner lands within a tick of the story itself.
Decisions
manual) so Settings can still edit it while an article overrides it. Binding the form to the effective value would have overwritten an admin's text with a headline on their next save.window_hours: 0is the meaningful "no limit" value — noteINTERVAL 0 HOURwould exclude every article, so the age clause is omitted from the query rather than passed as a sentinel.Added
idx_articles_breaking_news (breaking_news, pub_date)— the lookup runs on every homepage render and would otherwise scan the corpus to find nothing. Non-fatal at boot like the other index builders.Testing
10 new tests (6 database, 4 handler) pass against a real MariaDB 11.7, covering the scheduled case, newest-wins, archived/unflagged exclusion, the unlimited default, an admin-set window, and the settings round-trip. Full Go suite,
tsc, and the frontend tests are green.Not included
Scalene needs DrexelTriangle/Scalene#105 for the banner to become clickable, but nothing here depends on it —
/v1/homepagestill returnsbreaking_news: {enabled, text}witharticle_slugmerely added, so the public site picks up the article-driven banner with no deploy of its own.🤖 Generated with Claude Code
https://claude.ai/code/session_01ES8gPZxe6sb5xSLrBZ7AGk