Changelog Widget for Your Website: How to Embed One

2026-09-09 · ShipChangelog

The short version: a changelog widget is a small script that fetches your recent entries from a JSON or RSS endpoint and renders them where your users already are — the app sidebar, the docs, the pricing page. To embed one, paste a script tag pointing at your changelog's data endpoint, or build the same thing in about thirty lines of vanilla JavaScript with no dependencies.

Why a widget instead of just a /changelog page

A changelog page is something people visit when they think of it. A widget is something people see whether or not they think of it. The practical difference:

The full page still matters for the archive, RSS readers, and the occasional deep dive. The widget is the distribution layer on top of it.

What a widget actually is

Strip away the marketing terms and every changelog widget does the same three things:

  1. Fetch a data endpoint (JSON is the usual shape: array of entries, each with a date, a version, and a list of changes).
  2. Render the last N entries (3–5 is the working range) with a "view all" link to the full page.
  3. Do it cheaply: a few kilobytes, no cookies, no layout shift, no tracking.

If a widget does more than that, it is a product suite trying to rent space on your page.

Option 1: Copy-paste widget (vanilla JS)

Assume your changelog data is available as JSON at /changelog.json — most hosted changelog services expose exactly this, and a DIY version takes ten lines of Node. This script renders the last four entries:

<!-- put this where you want the widget -->
<div id="clg-widget" aria-label="Recent changes"></div>
<script>
  fetch("/changelog.json")
    .then(r => r.json())
    .then(entries => {
      const el = document.getElementById("clg-widget");
      const items = entries.slice(0, 4).map(e =>
        '<div class="clg-entry">' +
        '<span class="clg-date">' + new Date(e.date).toLocaleDateString() + '</span>' +
        '<ul>' + e.changes.map(c => "<li>" + c + "</li>").join("") + "</ul>" +
        '</div>'
      ).join("");
      el.innerHTML =
        '<div class="clg-head">What&apos;s new</div>' +
        items +
        '<a class="clg-more" href="/changelog">View full changelog &rarr;</a>';
    })
    .catch(() => {
      // fail silently: the widget is optional furniture, not critical path
      document.getElementById("clg-widget").remove();
    });
</script>
<style>
  #clg-widget { max-width: 280px; font-size: 13px; line-height: 1.45; }
  #clg-widget .clg-head { font-weight: 600; margin-bottom: 8px; }
  #clg-widget .clg-date { color: #8a93a6; font-size: 11.5px; }
  #clg-widget ul { margin: 4px 0 10px 16px; padding: 0; }
  #clg-widget .clg-more { font-size: 12px; }
</style>

The .catch() is the important production detail: if the endpoint is down or slow, the widget disappears quietly. A broken widget that blocks layout or spams console errors is worse than no widget.

Option 2: Serve the JSON yourself

If your site already runs on Node, the data endpoint is trivial:

app.get("/changelog.json", (req, res) => {
  // entries.json is what your release pipeline writes on each deploy
  res.sendFile(path.join(__dirname, "entries.json"));
});

The shape the widget expects:

[
  {
    "date": "2026-09-09",
    "version": "1.14.0",
    "changes": [
      "Added CSV export to reports",
      "Fixed a login timeout on Safari",
      "Breaking: /v1/sessions now requires a Bearer token"
    ]
  }
]

RSS works too if you would rather not run JSON — the widget above can be pointed at a feed parser instead — but JSON is less code and one fewer dependency.

Option 3: Hosted widgets and what to check before you trust one

If you do not want to maintain the script, hosted changelog services usually include a widget. Before you paste one into your app, check four things:

Placement rules that keep the widget useful

ShipChangelog

ShipChangelog covers the page side of this setup: it generates entries from your merged PRs, flags breaking changes, and serves a public changelog page with RSS and a badge you can drop into your site. A script-based widget in the shape above is on the roadmap; today the badge plus RSS give you the embed without any JavaScript of your own. Free for one repo with 5 entries a month.

FAQ

What is the best format for a changelog widget's data?

A JSON array of entries with date, version, and changes (a string array) is the simplest shape that survives contact with real release pipelines. RSS is a fine alternative when your changelog already ships as a feed and you do not want a second endpoint.

Should the widget update in real time?

No. Poll on page load, or refresh the page content when the user navigates. Real-time updates for a changelog are a waste of connections, and the content changes at most once per release — which for most teams is hours or days, not seconds.

Can a changelog widget replace email release announcements?

No — different jobs. The widget catches the users who are already in the product; email catches everyone else, including the ones who have not opened the app this week. Run both, and keep the email to the same three-or-four lines the widget shows, plus the link.

ShipChangelog writes these changelogs for you — start free with 1 repo.