Jeff Mixon / What's New: one feed for every changelog

Created Thu, 30 Jul 2026 00:00:00 -0700 Modified Thu, 30 Jul 2026 16:58:59 -0700

The premise

Software you rely on changed this week. You almost certainly don’t know how.

The information exists. It’s just scattered. One project cuts a GitHub release. One game posts patch notes to Steam. One IDE keeps a changelog page nobody links to. One OS files a knowledge-base article. One app writes “bug fixes and performance improvements” in a store listing and calls it a day. Every one of those is a reasonable decision by the people who made it. Together they add up to 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’s tracking around 685 products right now across open source, games, operating systems, desktop software and mobile apps, and it grows most days.

What it does

  • One feed of the newest releases across everything tracked, filterable by category.
  • Search across the whole catalog, not just what’s on the front page. A tool that ships once a quarter is still 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. You can link to one version instead of to a page that will have scrolled past it by Thursday.
  • RSS, because a feed of feeds should obviously be a feed.
  • A markdown view at /llms.txt and on every product page, for the growing share of readers that are language models.

Stack at a glance

  • App: Next.js 16 (App Router), React 19, TypeScript
  • Data: Postgres, with Drizzle as the ORM
  • Scheduling: cron on Vercel, one job per pipeline
  • 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 and Firefox
  • 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 one. 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. Nobody reading the site ever waits on GitHub being slow, or a vendor’s blog being down, or a rate limit that has nothing to do with them.

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

That means a source failing has to be a non-event. 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. One that keeps failing eventually gets marked dead rather than retried forever.

The failure I was actually worried about isn’t an outage. It’s the source that breaks so gently nobody notices it stopped producing. That’s how an aggregator rots while looking perfectly healthy, and most of the design around ingestion exists to make it loud instead.

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, mobile apps. Surely those would need it.

They mostly don’t, and finding that out reshaped the product.

Steam, the App Store, Google Play and GOG all expose structured, keyless endpoints that hand over patch notes already separated into fields. Windows publishes its update history as RSS. Minecraft’s launcher reads structured patch-note JSON. The Linux kernel, PHP and Firefox each publish a plain version list. Package registries have been publishing version history forever.

So What’s New reads first-party sources through their own interfaces wherever one exists, and the set of products that genuinely resist — bespoke enterprise changelog pages, a few storefronts, some console firmware — turned out much smaller than the roadmap assumed. Cost was the least of what that bought. Structured input means release dates that are really release dates, versions that are really versions, and notes that read the way the publisher wrote them instead of the way a model guessed.

Each kind of source is a small adapter behind one shared interface, which is the only extension point that matters. Supporting a new one means adding a file, not touching the pipeline. There are fifteen so far.

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 merely resemble them. So provenance gets rendered rather than assumed.

  • Hand-curated seed entries are labeled sample data. There’s some of it in the catalog while the long tail gets automated, and it never pretends to be a live feed.
  • An entry from a secondary source, a developer blog rather than 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” — gets marked as boilerplate instead of presented as a changelog. It isn’t information. Dressing it up as information is a lie the reader has no way to catch.
  • 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’s whole value is being found at the moment somebody asks “what changed in X?” Increasingly the thing asking isn’t a person with a browser.

So the same content ships five ways, all reading from the same database queries the pages use: the site itself, an RSS feed, a sitemap where each product’s last-modified date is the date of its newest release, markdown exports for language models, and server-rendered search results that need no JavaScript at all.

Two rules keep the structured data honest, and I’d rather say them out loud than quietly benefit from leaving them unsaid. 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. I didn’t write these release notes and nothing in the markup pretends otherwise. Second, no invented ratings, no invented prices, no newest-canary-posing-as-current-version. All three are available to me, all three would probably make the search result look richer, and all three would be a machine-readable lie.

Same reasoning 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.

Found by machines, decided by a person

There’s a second question underneath “what’s new,” which is what should be tracked at all. A catalog assembled entirely by hand stops growing the day I get busy.

So a nightly job sweeps several ecosystems for software popular enough to be worth following, collects what evidence it can, and works out whether there’s a source it could actually poll. 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 get polled, and a person — me — approves or rejects it.

Discovery only ever proposes. Automated curation without a 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 sticks.

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, and the request goes straight into discovery. Ten people asking for the same thing pushes it to the top. Asking for something already queued raises that candidate instead of creating a duplicate.

One small model, one narrow job

There’s exactly one place a language model touches this product. Most changelogs are prose, and the UI renders categories: added, changed, fixed, removed, deprecated, security. A small, cheap model turns one into the other.

It’s deliberately the least important component in the system. It runs on its own schedule, well after ingestion. It writes nothing but categories. If it isn’t configured at all, that step reports a clean “skipped” and every other part of the product works exactly as before.

That’s the shape I want for AI in a product like this. A narrow job, on a component you could delete, running the cheapest model that can do it, with the cost known before it’s spent. The interesting engineering wasn’t prompting. It was making sure the one component that costs money per item is also the one that almost never has to run.

What the adapters taught me

Writing a dozen-plus 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 out of a headline, parsing a date written six different ways, following an index page to find the notes it summarizes.

Every publisher independently invents a format, and every consumer independently reverse-engineers it. 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. It’s a proposal rather than a ratified format, argued from what actually broke while building this, and it borrows the vocabulary Keep a Changelog already got right before adding the handful of fields a consumer currently has to guess at. That’s its own post, and it’s coming.

Where it is now

whatsnew.fyi is live and reading real sources every day. It’s early. You can sign in, but an account doesn’t unlock anything yet — that’s groundwork for following specific products and getting a feed of your own, which is the next thing worth building.

Go look up something you use. If it isn’t there, the search box will offer to add it, and that box isn’t decoration. It’s the top of the queue I work from.