Skip to content

Follow a person, not just their publications - #136

Merged
ralyodio merged 1 commit into
mainfrom
author-follow
Aug 19, 2026
Merged

Follow a person, not just their publications#136
ralyodio merged 1 commit into
mainfrom
author-follow

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

/authors/anthony-ettinger could tell you who somebody is and hand you a feed of everything they write, and then had nothing for the reader who wanted to be told. Following was only ever a blog or a topic, which are the two things a person is not: somebody with a blog, a newsletter and a podcast is three rows in feeds, and following all three by hand still misses the fourth when they start it.

This adds the third kind of follow, with the same bell beside it.

Behaves like the other two, everywhere they do

  • The page renders the existing FollowControls, so the button flips in place and the bell appears beside it once you follow. Both are plain forms that still work with JavaScript off.
  • /following grows a People section with its own unfollow, and their posts merge into the river attributed to the person rather than to whichever publication carried them. That attribution is the entire reason for following a human.
  • The personal feed counts them, /account/alerts lists them, and an alert reads … · via Ada Lovelace.

One design choice worth reviewing

author_follows keys on author_id with a foreign key, which is the opposite of what topic_follows does. A topic slug is a topic's only identity, because topics is a rollup the poller rebuilds and a follow keyed to it would be deleted by a refresh. An author is a real row with a stable primary key and a unique identity_key the extractor merges on, and nothing in the codebase deletes one. So the FK is honest here, and it buys the cascade. A test pins it: deleting the author removes the follow rather than leaving one pointed at a 404.

The bug the tests found

usersWithAlerts decides which accounts the sender even looks at, and its EXISTS clauses were blogs and topics. A reader whose only alerts were on people would have been skipped entirely, silently, forever — the follow would record, the bell would light up, and nothing would ever arrive. alertingAccountCount carried the same predicate and the same gap, so it would then have under-reported the sender's own health on /crawlstats. Both now include the third table.

Verified

End to end in a headless browser against a seeded author with two feeds:

step result
signed out button invites sign-in, no bell
signed in, click Follow flips to Following ✓, no navigation
bell 🔕 Alerts off🔔 Alerts on
/following People section, names her, both posts in the river
/account/alerts lists her

Plus new tests: follow idempotency, the bell refusing a follow that does not exist, an alerting person yielding posts from every feed they write for, dead feeds contributing nothing, the FK cascade, river attribution, and dedupe when a post arrives by both a person and a topic.

pnpm -r test 1,093 pass / 0 fail, pnpm build clean, both on Node 22 (CI's version).

Not in scope

No follower count on the profile, and no backfill: an author follow starts alerting from the moment the bell is switched on, the same as the other two.

🤖 Generated with Claude Code

/authors/<slug> could describe somebody and hand you a feed of everything
they write, and then had nothing for the reader who wanted to be told.
Following was only ever a blog or a topic, which are the two things a
person is not: somebody with a blog, a newsletter and a podcast is three
rows in `feeds`, and following all three by hand still misses the fourth
when they start it.

So: a third kind of follow, with the same bell beside it.

`author_follows` keys on `author_id` rather than on the slug, which is
the opposite of what `topic_follows` does and deliberate. A topic slug is
a topic's only identity because `topics` is a rollup the poller rebuilds;
an author is a real row with a stable id and a unique identity_key the
extractor merges on, so the foreign key is honest and buys the cascade.
A test pins that: deleting the author removes the follow rather than
leaving one pointing at a 404.

It behaves like the other two everywhere they do. The page renders
FollowControls, so the button flips in place and the bell appears beside
it once following, and both are plain forms that work with JavaScript
off. /following grows a People section with its own unfollow, and their
posts merge into the river attributed to the person rather than to
whichever publication carried them, which is the entire reason for
following a human. The personal feed counts them, /account/alerts lists
them, and an alert says "via Ada Lovelace".

The delivery test found a real bug on the way in. `usersWithAlerts` asks
whether an account has any alerting follow, and its two EXISTS clauses
were blogs and topics: a reader whose only alerts were on people would
have been skipped by the sender entirely, silently and forever.
`alertingAccountCount` had the same predicate and the same gap, which
would then have under-reported the sender's own health on /crawlstats.
Both now include the third table.

Verified end to end in a browser against a seeded author with two feeds:
signed out the button invites sign-in and shows no bell; signed in it
flips to Following with no navigation; the bell turns on; and the person
then appears on /following with both her posts in the river, and on
/account/alerts. 1,093 tests pass, build clean, both on Node 22.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 6c78d88 into main Aug 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant