I now have four things that ship releases: Codex, Codex Reader, Tsundoku and Idle Beekeepers. Their release notes were spread across GitHub releases, the App Store, and a private repository nobody else can see. So I built one page for all of them: updates.4sh.dev.

One card per project with its current version, and the latest updates across all of them.

One card per project with its current version, and the latest updates across all of them.

How it works

It’s a static site. Once a day, a scheduled job imports new GitHub releases and App Store versions, keeps the features and fixes, and drops the noise (refactors, tests, chores). Each project gets a page with a short description and its full history.

A project page: what the app is, then every update.

A project page: what the app is, then every update.

The part that matters: a feed for Codex

The site also publishes a feed for each project, and Codex 2.7.0 now reads it.

Once a day, a Codex server downloads the Codex and Codex Reader feeds. Admins get a news icon in the header with an unread marker, and a drawer with the release notes. The sidebar shows the running version, and when a newer one exists it shows something like v2.6.3 → 2.7.0. Clicking it lists what changed in every version in between.

I was careful about privacy here, because every self-hosted Codex will make this request:

  • It’s a plain download of a static file, with nothing that identifies the server or its version.
  • “Is there an update?” and “what’s unread?” are worked out locally, on your server.
  • If it fails, nothing breaks: a server without internet access just shows an empty drawer.
  • One setting turns it off entirely, and then no request is made at all.

The feed is also a promise. Every Codex release with this feature will keep requesting it for years, so its address and format can’t change in a way that breaks them.

It’s a small project, but it closes a gap that matters for anything self-hosted: telling people a new version exists without learning anything about their server.