Skip to content

Changelog: group entries by release, replace pagination with scroll and search - #5590

Open
dimitrieh wants to merge 6 commits into
mainfrom
changelog/release-rail
Open

Changelog: group entries by release, replace pagination with scroll and search#5590
dimitrieh wants to merge 6 commits into
mainfrom
changelog/release-rail

Conversation

@dimitrieh

@dimitrieh dimitrieh commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

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 release frontmatter 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 in featureCatalog.yaml any more, and the handbook's frontmatter table and template are updated.

A node:test check 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=alternate that 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

  • I have read the contribution guidelines
  • I have considered the performance impact of these changes
  • Suitable unit/system level tests have been added and they pass
  • Documentation has been updated
  • For blog PRs, an Art Request has been created (instructions)

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.
@netlify

netlify Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploy Preview for flowforge-website ready!

Name Link
🔨 Latest commit 41d391c
🔍 Latest deploy log https://app.netlify.com/projects/flowforge-website/deploys/6a7eecfd7cba370008be4245
😎 Deploy Preview https://deploy-preview-5590--flowforge-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 64 (🟢 up 3 from production)
Accessibility: 96 (no change from production)
Best Practices: 100 (no change from production)
SEO: 85 (🔴 down 7 from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@dimitrieh

Copy link
Copy Markdown
Contributor Author

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.

@dimitrieh

Copy link
Copy Markdown
Contributor Author

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.
@dimitrieh

Copy link
Copy Markdown
Contributor Author

make the heading of "what's new" a little larger

adjusted

Comment thread nuxt/composables/useChangelogList.ts Outdated
Comment on lines +32 to +36
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))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
dimitrieh and others added 2 commits August 14, 2026 12:23
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants