# What's New: one feed for every changelog

> What's New collects release notes and patch notes from open source, games, operating systems and the apps on your phone into one feed you can read, search, follow, cite, and hand to your coding agent. How the pages avoid ever waiting on a third party, why almost nothing is scraped, how every entry shows where it came from, and what two months of growth changed.

By Jeff Mixon, published 2026-07-30. Canonical: https://www.jeffmixon.com/post/whatsnew-changelog-aggregator/

## The premise

Software you rely on changed this week, and you almost certainly don't know
how.

The information exists, but it's scattered. One project cuts a GitHub
release. A game posts patch notes to Steam. An IDE keeps a changelog page
nobody links to. An OS files a knowledge-base article. An app writes "bug
fixes and performance improvements" in its store listing and calls it a day.
Each of those is a reasonable choice by the people who made it. Put together,
they leave you with a question you can't answer without twenty browser tabs:
what changed in the things I use?

[What's New](https://whatsnew.fyi) is my answer. It reads all of those
places, normalizes what it finds into one consistent shape, and gives you a
single feed, newest first. It tracks about 1,700 products right now across
open source, games, operating systems, desktop software and mobile apps, and
the list grows most days.

*Updated September 2026.* When I first wrote this, the site was six days
old, tracked around 685 products, and an account didn't unlock anything.
Two months later it tracks about 1,700, accounts do real work, there's an
Android app, and coding agents can ask it questions directly. The architecture
held up. I've updated the sections on features, the model, and current status.

## What it does

- **One feed** of the newest releases across everything tracked, filterable
  by category.
- **Search across the whole catalog**, including products that aren't on the
  front page this week. A tool that ships once a quarter stays findable in the
  months it doesn't.
- **A page per product** with the full release history, rendered as real
  notes rather than a truncated blurb.
- **A permalink per release**, so you can link to one version instead of a
  page that will have scrolled past it by Thursday.
- **A comparison between any two versions** that lists every change in
  between. That's the question you actually have when you're three releases
  behind.
- **Following.** Follow what you use and get a personal feed that marks what's
  new since your last visit, with optional push notifications, a daily digest
  and keyword watches. You can also paste a `package.json`, Brewfile or
  requirements file and follow everything in it at once.
- **RSS**, because a feed of feeds should obviously be a feed. There's also
  one that carries only security fixes.
- **A weekly roundup** of what shipped, plus a newsletter that needs no
  account.
- **A markdown version of any page**, plus `/llms.txt`, for the readers that
  are language models.
- **An MCP server** for the readers that are coding agents (more below).
- **An Android app** on Google Play, and posts to Bluesky and Mastodon when
  something notable ships.

## Stack at a glance

- **App:** Next.js 16 (App Router), React 19, TypeScript, in a small
  workspace monorepo with the resolver tooling alongside
- **Data:** Postgres, with Drizzle as the ORM
- **Scheduling:** cron on Vercel, one job per pipeline (there are ten now)
- **Styling:** Tailwind v4 and shadcn/ui, light-first with a dark toggle
- **Testing:** Vitest, split into a fast Node project for logic and a
  component project that runs in real Chromium, Firefox and Edge
- **CI/CD:** a self-hosted GitLab pipeline that lints, type-checks, tests,
  scans, deploys, and then re-tests the deployed site from outside

## Nothing is fetched while you wait

The most important architectural decision in the project is also the most
boring: fetching and serving are completely separate.

Scheduled jobs poll sources on their own clock and write normalized releases
into Postgres. Pages read Postgres. That's the whole rule, and no page render
anywhere in the app contacts a third-party origin. If GitHub is slow, a
vendor's blog is down, or someone else's rate limit kicks in, readers never
notice.

Pages come back fast because there's nothing to wait for. They keep working
when an upstream source doesn't, since the worst a broken source can do is
stop adding new entries while everything already stored keeps serving. The
read path is also cheap enough that I don't have to think about traffic,
which matters when one person is paying the bill.

A failing source still has to be a non-event on the ingestion side. When one
goes down, rate-limits, or quietly changes shape, it fails alone. The failure
gets recorded, that source backs off and retries on a widening schedule, and
the rest of the run carries on. A source that keeps failing eventually gets
marked dead instead of being retried forever.

What I actually worried about was quieter than an outage: a source that
breaks so gently nobody notices it stopped producing. That's how an
aggregator rots while looking healthy, and most of the ingestion design exists
to make that failure loud.

## Almost nothing here is scraped

I went in assuming a big chunk of this project would be HTML scraping, with a
language model reading marketing pages to guess at what changed. Games,
console software and mobile apps seemed like obvious candidates.

They mostly aren't, and finding that out reshaped the product.

Steam, the App Store, Google Play and GOG all have structured, keyless
endpoints that return patch notes already split into fields. Windows keeps
its entire update history in one server-rendered page. Minecraft's launcher
reads structured patch-note JSON. The Linux kernel, PHP and Firefox each
publish a plain version list, and package registries have been publishing
version history forever.

So What's New reads first-party sources through their own interfaces wherever
one exists. The products that genuinely resist (bespoke enterprise changelog
pages, a few storefronts, some console firmware) turned out to be a much
smaller set than the roadmap assumed. Lower cost was the least of what that
bought. Structured input gives you release dates that are really release
dates, versions that are really versions, and notes worded the way the
publisher wrote them rather than the way a model guessed.

Each kind of source is a small adapter behind one shared interface, and that
interface is the only extension point that matters. Supporting a new kind
means adding a file without touching the pipeline. There were fifteen when I
first wrote this. There are twenty-two now, including GitLab, Flathub and the
appcasts Mac apps use to update themselves. A handful of pages only exist
after JavaScript runs, so a headless browser renders those in a throwaway
sandbox, with the same checks that guard every other fetch applied before and
after.

Sources also change underneath you, which is the other reason failure handling
matters. In August, Microsoft permanently retired its support RSS feeds. I
didn't hear it from a user. The source-health table flagged Windows 11 as
degraded after six failures in a row.

## Every entry tells you where it came from

The fastest way to make an aggregator worthless is to flatten everything into
one confident-looking stream that mixes real release notes with things that
only resemble them. So provenance is shown on the page instead of assumed.

- Hand-curated seed entries are labeled as sample data. There's some in the
  catalog while the long tail gets automated, and it never passes itself off
  as a live feed.
- An entry from a secondary source, such as a developer blog instead of the
  official release stream, says so. A blog post is not a release note.
- Publisher boilerplate ("we update the app regularly to fix bugs and improve
  performance") is marked as boilerplate. Presenting it as a changelog would
  pass off filler as information, and the reader would have no way to tell.
- Pre-releases are labeled, and never shown as the current version of
  anything.

The labels travel with the content into the RSS feed, the markdown exports and
the structured data, so a consumer that never renders a page still gets the
caveats.

## Built to be quoted

A changelog aggregator is only useful if it gets found when somebody asks
"what changed in X?", and more and more often the one asking isn't a person
with a browser.

So the same content goes out in many forms, all built from the same database
queries the pages use: the site itself, RSS feeds, a sitemap where each
product's last-modified date is the date of its newest release, a markdown
version of every page for language models, server-rendered search results
that need no JavaScript, structured data, and an MCP server. When something
changes, the site notifies search engines instead of waiting for a crawler to
come back.

Two rules keep the structured data honest, and I'd rather state them than
quietly benefit from leaving them out. First, this is an index, not a
publisher. Every product's structured data points at the vendor's own site
and names the vendor as the author, because I didn't write these release
notes. Second, nothing is invented: no ratings, no prices, and no canary build
dressed up as the current version. Any of those would probably make a search
result look richer, and each one would be a false statement in
machine-readable form.

The same reasoning is behind giving every release its own permalink. If you
want to cite what changed in version 4.2 of something, you should be able to
link to version 4.2.

## Answering agents, not just people

The newest kind of reader is a coding agent partway through a dependency
upgrade. What's New runs a public MCP server at `whatsnew.fyi/mcp`, listed in
the official MCP registry. It needs no key and no account, and an agent can
use it to ask what's new in a product, search releases, or list what's
tracked.

The two tools I care about most are also the least clever. One answers "what
changed between the version I have and the version I'm moving to?" for each
dependency. The other takes an outdated-dependency report and separates what
you'd pick up by moving to the version you allowed from what you'd get at the
latest, counting security fixes and breaking changes on each side. Neither one
calls a model. They use the same version-range logic as the site's compare
page, and a test checks that the two always agree, because an agent planning
an upgrade should see exactly what a person would.

## Found by machines, decided by a person

Underneath "what's new" sits a second question: what should be tracked at
all? A catalog assembled entirely by hand stops growing the day I get busy.

So a scheduled job sweeps more than a dozen places for software popular
enough to be worth following. It collects whatever evidence it can and works
out whether there's a source it could actually poll, and then it stops. Every
candidate lands in a private review queue with its evidence and links to both
the project and the exact source that would be polled. A person, me, approves
or rejects it.

Discovery only ever proposes. Automated curation without a human gate is how
you end up with an index full of abandoned repositories and name collisions.
A candidate with no pollable source can't be approved at all, and a rejection
is permanent.

The most useful signal in that queue turns out to be you. Search for
something that isn't tracked and the empty state offers to add it, sending
the request straight into discovery. If ten people ask for the same thing, it
goes to the top. Asking for something that's already queued raises that
candidate instead of creating a duplicate. Importing a manifest counts too,
but only for names a public registry confirms exist, so a private package
name never gets stored.

## Small model, narrow jobs

When I first wrote this, a language model touched the product in exactly one
place. Most changelogs are prose, the UI shows categories (added, changed,
fixed, removed, deprecated, security), and a small, cheap model converted one
into the other.

It has a few more jobs now, all of the same shape. It writes the one-paragraph
summary at the top of each weekly roundup, based only on that week's
releases. For projects that opt in and ship without notes, it turns the commit
messages between two tags into categorized changes, and every surface labels
those "From commit messages" because they aren't the publisher's words.

What it never decides is just as deliberate. It doesn't pick what gets posted
to Bluesky or Mastodon; that comes from a popularity threshold or a security
fix, and a machine-written entry is never posted at all. It doesn't decide
what counts as a security fix, and it never produces a CVE number, which is
either extracted verbatim from the notes or left out. When no model is
configured, each model step reports "skipped" and everything else keeps
working.

When cheaper models came out, I didn't switch because of a price list. I
re-ran a sample of real production work through the candidates and scored
them against how consistently the current model agrees with itself. None of
them cleared the bar, so nothing changed. That's how I want AI used in a
product like this: narrow jobs, on components you could delete, run by the
cheapest model that has *measurably* earned the work, with the cost known
before it's spent.

## What the adapters taught me

Writing more than a dozen of these adapters teaches you something
uncomfortable. Very little of that code aggregates anything. Almost all of it
recovers structure that publishers already had and threw away: inferring
categories from prose, digging a version number out of a headline, parsing a
date written six different ways, following an index page to find the notes
it summarizes.

Every publisher invents its own format, and every consumer reverse-engineers
it separately. That's an enormous amount of duplicated work for a document
that, in most cases, is already Markdown.

I've written up what a changelog would look like if it needed none of that
recovery work: [Declarative Changelogs](https://whatsnew.fyi/spec). It's a
proposal, not a ratified format, and it's argued from what actually broke
while building this. It borrows the vocabulary
[Keep a Changelog](https://keepachangelog.com) already got right, then adds
the handful of fields a consumer currently has to guess at. A conforming file
still reads as an ordinary `CHANGELOG.md`. There's an
[open-source validator](https://github.com/whatsnew-fyi/declarative-changelog)
on npm, and my own [Knit](https://getknit.app) app writes its release notes in
the format. The full argument deserves its own post, which I still owe.

## Where it is now

[whatsnew.fyi](https://whatsnew.fyi) is live, and ingestion runs every hour
(each source is still polled on its own adaptive schedule). The follow-a-product feed that I called "the next thing worth building"
in July has shipped, along with push notifications, email and the Android
app. The site also publishes a few living
[research reports](https://whatsnew.fyi/research) that are recomputed from the
whole corpus. One finding so far: roughly a quarter of App Store release notes
say nothing at all.

Go look up something you use. If it isn't there, the search box will offer to
add it. That request goes into the same queue I review.
