buildnotes Example 3 of 3 · Release Notes Index

Making the weekly digest worth opening

A collection's weekly digest now opens with a picture of the week, can play that week back, and comes to your inbox on Monday.

Every Monday, Release Notes Index writes a short digest for each collection: a few paragraphs on what the products in it shipped the week before. The digest was our most readable page, but you only saw it if you went looking for it. And you had to read all of it to learn which releases mattered. So we added three things:

The hard parts were deciding what "biggest release" should mean, and sending each email once and only once.

01The week at a glance

A digest explains why each release matters, but it's a lot to read when you just want the highlights. When you open the Coding Agents digest, you want to know two things first:

The card answers both before the first paragraph. On top is a treemap with one tile per product. The size of a tile shows how much that product shipped. Colored columns in each tile split its work into features, enhancements and fixes. A flame on a tile marks each release we score as major or landmark.

Under the treemap is a list of the five biggest releases. Each row links to the part of the digest that talks about it. Click a tile, and the list shows only that product's releases.

View
The week at a glance
  1. Flames. One for each major or landmark release; a landmark's is filled.
  2. Tile size. How much the product shipped, measured as impact.
  3. Columns. Features, enhancements and fixes, left to right.
  4. Click a tile and the list shows only that product's releases.
  5. The five biggest releases. Each row links to the part of the digest about it.
Fig. 1. The card for Coding Agents, week of 28 September, as built. Claude Code had the most releases, but most of them were fixes, so its tile is smaller than Codex's. Drawn at an angle from the shipped card: point at a number to read what that part is, or take it apart.

The first real choice was which releases the card should count. A collection can have releases that the digest doesn't mention, usually small patches. We could count every release from the week, or only the ones the digest covers.

We chose the covered ones. The card is a summary of the digest you are reading. Every tile and every row links into the digest text, and a release the digest skips would have nowhere to link to.

This has a cost. In a week where the digest leaves out a lot of small activity, the card counts less than really shipped. If that becomes a problem, the fix belongs where the digest is written, so the digest covers more. The card should never disagree with the text under it.

The card also knows when to stay out of the way. With fewer than three releases in a week, the text is enough, so the card doesn't appear. If only one product shipped, a single tile says nothing, so the card shows only the list.

02What counts as impact

The first idea for tile size is the number of releases, and it gives the wrong answer. In the week shown above, Claude Code had six releases and Codex had four. But about two-thirds of Claude Code's work was fixes, and Codex launched a new default model. A tile sized by count would tell you that Claude Code had the bigger week.

So a tile's size is its impact, which we build from two signals we already store for every release. The first is importance, a score from 1 to 5 given to each release when we index it. A release scored 3, 4 or 5 counts as 2, 3 or 4 points. The second is composition, the count of features, enhancements and fixes inside the release. A feature counts in full, an enhancement counts three quarters, and a fix counts half. A release's points are scaled by that mix. When we don't know the mix, we use a flat 0.6.

Small releases needed one more rule. Some teams tag a release for every patch. If each patch added points on its own, a busy week of small fixes could outweigh one large launch. So a product's minor releases (importance 1 or 2, or not scored) share one pool. The pool grows quickly at first and then levels off. It can never pass 4 points, the value of one landmark release made of features.

1 patch0.15
10 patches1.25
20 patches2.11
40 patches3.11
1 landmark4.00
Fig. 2. Impact of a product's patch releases (importance 1, mix unknown) against one landmark release made of features. Computed with the shipped impact function.

The colors carry a choice too. Fixes use a pale red, mixed at 30% strength into the tile's background. At full strength, a tile that is mostly fixes looks like an error. Its red band also draws the eye away from the green features band, which is the work the tile size is meant to reward. At 30% it still matches the red used for fixes elsewhere on the site, so the two read as one system.

All of this lives in one small function with no side effects. It takes the week's releases and returns the tiles and the ranked list. The card only draws what that function returns. That choice paid off in the next part.

03Playing the week back

A finished week has a shape that a static card hides. Some products ship on Monday and go quiet. Others save a large launch for Thursday. The replay shows that shape. It plays the week back day by day, with one lane per product and one mark per release. Beside the lanes, the impact map grows as releases land. A caption names the biggest release of the day so far.

TuesdayReplay paused on Tuesday: four product lanes with release marks on Monday and Tuesday, a caption for the landmark Codex launch, and a partly grown impact map
End of the weekReplay at the end of the week: all release marks placed, and the impact map and list now match the week at a glance card
Fig. 3. Two frames of the replay for the same week. The last frame is the week at a glance card.

The replay ends on the card. Its last frame has the same tiles in the same places and the same five releases. So the replay ends where the digest begins. To get that, the replay doesn't use a second copy of the impact math. At each moment, it runs the same function as the card on the releases shipped so far. At the end, "shipped so far" is the whole week, so the final frame is the card. A test checks that the two are equal. Tiles also keep their final order through the whole replay, so they grow in place and don't swap positions.

A few more decisions set how it feels:

You reach the replay from a "Replay the week" link on the card. The link appears only when the card does, so it never points at a week too small to replay.

04One email per reader per week

The card and the replay make the page better, but a reader still has to visit it. The email brings the digest to them. The collection page and each digest page now have an "Email me this digest weekly" toggle. You need an account to use it. On Monday, when the digest for the week that just closed is written, each subscriber gets a short email. It has:

We first had to decide what subscribing means. Release Notes Index already lets you follow organizations and products, and a follow shapes your feed. We could have let people follow a collection and send email to its followers. We chose a separate subscription instead. A follow keeps one meaning, "show me this in my feed", and email stays something you turn on for each collection. Unsubscribing from one collection's email, with one click, leaves the rest of your settings alone.

Then we had to send each email exactly once. Two things make that harder than it sounds:

How a weekly digest email is sent The Monday digest run checks whether the week just closed. If not, no email is sent. If so, it creates one message per subscriber on the delivery queue. Each message claims the week for that reader. If the claim succeeds, the email is sent; if the week was already claimed, the message is skipped. Monday run writes digests Week just closed? not a catch-up week One message per subscriber Delivery queue may deliver twice No email old or forced weeks Send email failure: undo claim Claim the week per reader yes no each message won already claimed: skip
Fig. 4. Two checks stand between a digest and your inbox. Only the week that just closed sends, and each reader's copy must win a claim first.

The first check is about which weeks send. Only the week that just closed sends email. A catch-up run for a missed week, a forced rewrite of an old digest, or a backfill never emails anyone. Nobody wants a "this week" email about last month.

The second check is the claim. Each subscription row stores the last week it was sent. Before sending, the delivery step moves that week forward, but only if it is still behind:

apps/api/src/queries/collection-digest-subs.ts
  const updated = await db
    .update(userCollectionDigestSubs)
    .set({ lastSentWeek: weekStart })
    .where(
      and(
        eq(userCollectionDigestSubs.userId, userId),
        eq(userCollectionDigestSubs.collectionId, collectionId),
        or(
          isNull(userCollectionDigestSubs.lastSentWeek),
          lt(userCollectionDigestSubs.lastSentWeek, weekStart),
        ),
      ),
    )
    .returning({ id: userCollectionDigestSubs.id });
  return updated.length > 0;

The update and the check are one statement, so only one delivery can win. A message delivered twice finds the week already claimed and stops without sending. If the send itself fails, the claim is undone, so the queue's retry can try again.

One trade-off is still open. The email ranks its five releases by importance alone, and keeps ties in the order the digest cites them. It doesn't use the card's impact math, which lives in the web app. For the top five the two orders mostly agree, but they can differ when releases tie on importance. Our plan is to move the impact math into shared code only when another part of the system needs the same numbers.

05On for every new collection

Weekly digests were opt-in for each collection, turned on with a manual database change. They are now on by default for every new collection. A collection can still be turned off through the API.

The default lives in the application, not in the database table. Our database is SQLite, and SQLite can't change a column's default without rebuilding the table. That rebuild would also touch every table that points at collections, including the new subscriptions table. The only code that creates collections goes through the same layer that now supplies the default, so we set it there. Existing collections didn't need a change, because all of them already had digests on.

Your subscriptions also appear on your account's notifications page, where you can turn any of them off. Email goes only to verified addresses. If yours isn't verified, the toggle tells you so and offers to resend the link, so a subscription never fails without a word.

To try it, open any collection's latest digest. Look at the week at a glance, press "Replay the week", and turn on the email if you want next Monday's digest in your inbox.

This post is a buildnotes example

The same story in one minute

buildnotes wrote this post from the pull requests behind one Release Notes Index feature, then cut the video from the post: every word, number and screenshot in it comes from the page above.

Walkthrough videosSunny · post and 52 seconds video Before and after, side by sideuploads.sh · post and 47 seconds video