Changelog Page Template in React: RSS, Email, Permalinks
A changelog page is where a buyer checks whether your product is still moving and where a user finds out the thing they asked for shipped. Most of them fail at the second job: nobody remembers to visit a page, so the release that took a month gets read by five people. This tutorial builds a changelog page template in the Next.js App Router that people come back to: dated releases grouped as New, Improved and Fixed, a page per release, an RSS feed and an email signup, all fed from one data file. The UI is our Changelog Page template, so we are not neutral, but the data model, the routes and the feed work the same with any React changelog component or release notes page template.
What makes a SaaS changelog worth reading?
A SaaS changelog gets read when it is easy to scan and easy to follow. The first part is mostly agreed on. Keep a Changelog 1.1.0 (opens in a new tab) (checked November 6, 2026) lists the principles: written for people, an entry for every version, changes of the same type grouped together, versions you can link to, the latest first, and a release date on each, with ISO format (2026-11-06) as the recommended way to write it.
Keep a Changelog groups by six types: Added, Changed, Deprecated, Removed, Fixed and Security. That suits a developer library. For a product changelog read by customers, fewer groups are easier to scan. Gleap's changelog template (opens in a new tab) (updated September 27, 2026, checked November 6, 2026) leads with New, Improved and Fixed, adds Deprecated and Security, and warns that too many labels make a changelog harder to scan. We go one step further and keep three. This is how the six map onto them:
The second part, following, gets less attention. When we searched "changelog page template" on November 6, 2026, the top results were page builder templates (Framer, Ceptile), a Next.js and MDX starter on GitHub, and copy-paste text formats for a single entry. They focus on how the page looks. Little of it covers the three things that bring readers back: a link per release that keeps working, a feed, and an email when something ships.
How do you install the changelog page template?
One command copies the template and the parts it imports. It is a Pro item, so the account behind the CLI needs Wingo UI Pro.
You get components/templates/changelog-page.tsx and changelog-page-data.ts, plus what they use: the free Marketing Section (for the page backdrop, the heading and the email form), the Marketing Header and Footer, the Segmented Control for the New / Improved / Fixed filter, the Badge for group labels and the Latest tag, and the Pagination for Load older releases. With no releases prop it renders eight sample releases of a made-up product called Acme.
$ npx wingo-ui@latest add changelog-pageHow do you store releases so the page, the feed and the emails agree?
Put them in one plain TypeScript file. The page, the per-release pages, the RSS route and anything that sends email all import it, so a release cannot appear in one and be missing from another.
The type import costs nothing on the server: types are erased at build time, and changelog-page-data.ts has no "use client" directive anyway, so you could import CHANGELOG_RELEASES from it too. The slug helper is different: changelog-page.tsx is a client module, and a server component that calls a function exported from one gets an error instead of a string. Copying the one-line helper keeps your slugs identical to the template's anchors, so 1.4.0 becomes v1-4-0 everywhere.
glyph and tone pick the drawn cover (the glyph keys are in CHANGELOG_GLYPHS: timeline, repeat, workflow, doc, chart, plug, cloud, shield, sparkles). Pass cover with an image URL to use a screenshot instead.
How do you render the changelog page in the App Router?
Split it in two, as with any client template: a server page.tsx for metadata and a small client wrapper for everything that is a function (linkComponent, onSubscribe).
Three props are easy to miss. With header={false} the template stops reserving room for its own sticky bar, so pass your header's height through --topbar-offset or the rail slides under it. Without onLoadMore, Load older releases waits 700 ms to imitate a request; a no-op makes it instant when the data is local. And every visible string lives in labels: the title says Acme and the description promises a weekly release until you change them.
Why does each release need its own page?
Because the anchor link breaks once the list paginates, and because one release at one URL is the easiest thing to share. Every release on the page has an id (v1-4-0), and the version pill links to it. But the page renders only pageSize releases at first (4 by default), so a link to /changelog#v1-0-0 from an old email lands at the top of a page where that release does not exist yet.
A static page per release fixes that, and it gives RSS items, emails and posts a link that always works. ChangelogReleaseEntry, the part the template uses for each release, renders one on its own:
The release is plain JSON, so it crosses from the server page to the client wrapper without trouble. Note the subscribers={0}: the Newsletter Section defaults to a sample count of 12,400 readers, which is fine in a demo and a fabricated number on your site. Zero hides the proof line.
$ npx wingo-ui@latest add newsletter-sectionHow do you add an RSS feed to a Next.js changelog?
A route handler that reads the same releases and returns RSS 2.0. Link each item to its release page, and put the grouped changes in the description so readers see the whole release without leaving their feed reader.
The description is HTML escaped twice on purpose: once for the text inside the HTML, once so the HTML itself is valid inside XML. Since Next.js 15, GET route handlers are not cached by default, so force-static is what turns the feed into a file built once per deploy. With Cache Components turned on, drop that line: a handler that reads no request data is prerendered anyway. Noon UTC (T12:00:00Z) keeps the release on its calendar day for readers from UTC-12 to UTC+11; the template goes further and formats its dates in UTC, so every visitor sees the same day. For a live changelog page example, our own changelog works this way, with a page per version and an RSS feed. If you also run a blog, the Next.js blog template post covers a JSON Feed next to RSS.
How do you wire the email signup?
onSubscribe gets the trimmed, already validated email. The form spins while the promise runs, shows the success line when it resolves and the error line when it rejects. That last part matters: a Server Action that returns { ok: false } still resolves, so the visitor sees "You're in". Throw instead.
Use double opt-in and answer the same way for a new, pending or existing address, so the form cannot be used to check who is on your list. The default success line already says "Check your inbox to confirm", which matches that flow. When you publish a release, send one short email per release with the title, the summary and a link to its page. That makes the page per release the target of every email you send.
How do you show what's new inside the app?
The public page reaches people who look for it. Users who are already signed in are easier to reach: put the last few releases inside the app, in a "What's new" panel or the help menu. A full changelog page is too heavy there; the Timeline fits a side panel and reads the same data.
timePosition="side" puts the dates in a column on the start side once the timeline is 512px wide and folds them under the title in a narrow panel or on a phone. It is a container query, so it reacts to the panel's width. timeFormat="date" prints the day; the default relative ("3 days ago") suits activity feeds better than releases. Each title links to the release page.
What are the common mistakes on a changelog page?
- Commit messages as entries. "fix tz offset in date util" means nothing to a customer; "Due dates no longer shift by a day across time zones" does. Write the symptom the user saw.
- Bundling. One change per line. A new integration and a billing fix are two entries, in two groups.
- Long gaps. A changelog whose newest entry is five months old tells a buyer the opposite of what you want. Ship small releases and write them up as you go.
- Dead follow buttons. The template's RSS button points at
/changelog/rss.xmlby default. Build the route or passrssHref=""to hide it. - Sample content in production. Search the rendered page for Acme before launch: the default title, the description, the newsletter count and, if you keep them, the template's own header and footer.
For the rest of the marketing site (pricing, contact, legal, about), the SaaS website template guide covers each page and how they share one layout, and more step-by-step builds sit in the Build it category. The support side of the same site, with search, topics and articles, is in our help center template guide.
Where do you start?
Copy the data file and the routes above, then install the template with npx wingo-ui@latest add changelog-page and replace the sample releases with your last three. The template, the Timeline and the Newsletter Section are part of Wingo UI Pro, $8 a month, $80 a year or $150 once (pricing); you can click through the Changelog Page template in all three designs (classic, minimal and editorial) before you decide.
FAQ
What should a SaaS changelog page include?
Releases newest first, each with a version, an ISO date, a short title, a one-sentence summary and its changes grouped by type (new, improved, fixed). Add a permalink per release, an RSS feed and an email signup so readers can follow it without remembering to check.
What is the difference between a changelog and release notes?
A changelog is the running record of every release, in one place and one format. Release notes usually describe a single release in more depth, often as an email or a blog post that links back to its changelog entry.
How do I add an RSS feed to a Next.js changelog?
Add a route handler at app/changelog/rss.xml/route.ts that reads the same releases array as the page and returns RSS 2.0 XML with the content type application/rss+xml. Mark it force-static and list it in the page metadata under alternates.types so feed readers find it.
Should each changelog release have its own page?
Yes, once you have more releases than fit on the first screen. A static page per release gives RSS items, emails and social posts a link that always works, and each page can carry its own title and description for search.
Is the Wingo UI Changelog Page template free?
No. The Changelog Page template, the Timeline and the Newsletter Section are Pro items, installed with npx wingo-ui@latest add once your account has Pro. The Marketing Section they build on is free.
- Changelog
- Next.js
- Templates
- RSS
