Changelog: group entries by release, replace pagination with scroll and search - #5590
Changelog: group entries by release, replace pagination with scroll and search#5590dimitrieh wants to merge 6 commits into
Conversation
Adds a `release` field to every changelog entry, derived from the entry's own date against the release milestone calendar: an entry belongs to the first release dated on or after it, because a post is published once the change is live on FlowFuse Cloud and self-hosted users receive it in the next release. Where the milestone due date and the release blog date disagree, the milestone is correct. At the 2.14/2.15 boundary the entries dated either side are all described in the 2.14 blog, matching the milestone rather than the blog date. The field must be declared in the content schema or @nuxt/content strips it from the entry, which is what silently happened to `tags`. A node:test check validates the frontmatter of every entry: required fields present, a zero-padded real calendar date, a MAJOR.MINOR release, and release numbers that never decrease as dates increase. That last invariant needs no release calendar in the repo and catches a mistyped release against its neighbours. Also fills in the entry descriptions that were empty, since they render as blank rows on the listing, adds the changelog tag where it was missing, and zero-pads a malformed date.
Each release labels its own entries from a sticky column beside them, so the label lines up with the entries it belongs to and stays in view while you read through that release. The label column carries the same vertical rhythm as an entry so the two line up, and the spine border starts level with the label rather than leaving a stub above it. The listing is now a single page. Entries reveal as you scroll rather than paging, and a search box filters on title and description. The whole archive was already fetched in one query and sliced, so this changes what is rendered rather than what is loaded. The numbered /changelog/<n>/ routes redirect back to the listing and are dropped from the prerender list. Adds the link rel=alternate that advertises the existing Atom feed, which nothing pointed at before, so readers and browsers can discover it, and labels the feed icon. Sticky positioning lives on wrapper elements rather than the headings: style.css sets `position: relative` on h1 through h4, which outranks the sticky utility and turns the offset into a downward nudge over the content.
✅ Deploy Preview for flowforge-website ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Related slack thread: https://flowfuse.slack.com/archives/C03FAUBPPJ7/p1786557212500649 @allthedoll this includes a change to every changelog entry so that a release is noted in the front matter (therefore so many files) and an adjustment of the handbook page instructing about creating changelog entries, plus tests for it. |
|
open question: this page now has its own rss. Do we want the merge this into the blog rss? |
.ff-blog leaves h1 at 16px and weight 400, the same as the subtitle directly below it, so "What's new" did not read as a heading. Sets it above the entry titles instead.
adjusted |
| const matching = computed(() => { | ||
| const term = search.value.trim().toLowerCase() | ||
| if (!term) return entries.value | ||
| return entries.value.filter(e => | ||
| e.title?.toLowerCase().includes(term) || e.description?.toLowerCase().includes(term)) |
There was a problem hiding this comment.
@dimitrieh the Algolia search was already implemented before migrating to Nuxt, iirc, ZJ intentionally removed it. If we want to bring the search back, could we use Algolia like the rest of the site instead? That way we don't lose the full-text search, fuzzy matching and keep it consistent across the site.
There was a problem hiding this comment.
Switched to <AlgoliaSearch index-filter="category:changelog" />, the same component the blog, docs and handbook use.
Checked the index before changing it: /changelog/ is already in ALLOWED_ROOT_SCOPES in lib/search-index.js, so every entry is in prod_netlify with its body text under category:changelog. My filter only matched title and description, so this reaches the bodies too and tolerates typos.
| you read through them. Two columns per release, not one list plus one nav. --> | ||
| <section | ||
| v-for="group in visibleGroups" | ||
| :id="anchorId(group.release)" |
There was a problem hiding this comment.
While going through the deploy preview, I was expecting these to be interactive, actual shareable anchors. Was it deliberate to make them static? Is it related to the infinite scroll choice?
There was a problem hiding this comment.
Not deliberate. The ids were there but nothing linked to them. The sticky label and the mobile heading are both anchors now.
It was related to the scroll choice though. A link like /changelog/#release-2-20 had nothing to scroll to on arrival, since only the newest entries are rendered. The listing now renders through that release first, then scrolls to it. Tested back to #release-1-12, the oldest one.
Search was a client-side filter over title and description. Algolia already indexes every changelog entry under category:changelog, and the blog, docs and handbook all search through it, so use the same component here. That reaches entry bodies and tolerates typos rather than matching substrings of frontmatter. The release labels carried an id but nothing linked to it. They are anchors now. A shared link can name a release below the initial slice, which has no anchor to scroll to yet, so the listing renders through that release before scrolling.
The reveal ran once at mount and once if the entries changed after it. On the deploy preview the first cold load of /changelog/#release-1-12 landed at the top of the page with the release never revealed, so that pair of triggers is not enough. It now retries whenever the archive or the hash moves, and tracks which hash it acted on rather than latching a boolean, so a second link and the back button both resolve. Scrolling is instant. The site sets scroll-behavior: smooth, and animating a jump of tens of thousands of pixels to an old release is not worth watching.

Description
Reframes the changelog around releases, so a reader can see what shipped in each one and self-hosted users can tell which release a change reaches them in.
Each release labels its own entries from a sticky column beside them, so the label lines up with the entries it belongs to and stays in view while you read through that release. The listing is a single page now: entries reveal as you scroll instead of paging, and search runs on the Algolia index the blog, docs and handbook already use, filtered to
category:changelog, so it reaches entry bodies rather than just frontmatter. Each release label is an anchor for its own release, and a link to a release below the initial slice renders through to it before scrolling. Numbered/changelog/<n>/routes redirect back to the listing.Entries carry a new
releasefrontmatter field. It was backfilled across the archive from each entry's own date against the release milestone calendar, on the rule that an entry belongs to the first release dated on or after it, since a post goes up once the change is live on Cloud and self-hosted receives it in the next release. Nothing needs to be recorded infeatureCatalog.yamlany more, and the handbook's frontmatter table and template are updated.A
node:testcheck validates every entry's frontmatter, including an invariant that release numbers never decrease as dates increase, which catches a mistyped release without needing a release calendar in the repo.Also adds the
link rel=alternatethat advertises the existing Atom feed at/changelog/index.xml, which nothing pointed at before.Two incidental fixes the listing exposed: entry descriptions that were empty rendered as blank rows, and one entry's date was not zero-padded.
Related Issue(s)
No tracking issue. Came out of a Product and Marketing discussion about framing the changelog page.
Checklist