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 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. 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 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
on npm, and my own Knit 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 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 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.