homemixer.
a live, no-storage port of the pipeline shape behind github.com/twitter/the-algorithm's home-mixer — running over the Bluesky Feed API instead.
what this actually is
@skeet.best asked for a port of the "X Recommendation Algorithm" to the Bluesky Feed API. That repo's real ranker is a trained multi-task neural net over ~6,000 features, fed by Twitter-internal services (Earlybird, UTEG/GraphJet, a live engagement stream) with no atproto equivalent — and this bot's house rules ban Workers AI outright, so there's no model to run here even if the weights were public, which they never were.
What's genuinely portable, and what this ships: the pipeline shape
home-mixer's own docs describe, and the relative weighting Twitter
published when it open-sourced the ranker's tunable params
(home_mixer_model_weight_fav / _retweet / _reply,
among others) — replies weigh far more than reposts, reposts more than likes. This
site substitutes realized public engagement counts for the trained per-user
propensity scores those params actually held, and a hand-set weight table for the
learned one.
- candidate sourcing
- light rank
- heavy rank
- author diversity
- in/out-of-network mixing
In-network candidates come from a live sample of accounts you follow; out-of-network candidates come from a 2-hop walk of the follow graph (follows of your follows), the same shape as UTEG's graph traversal, just over the public follow graph instead of a private engagement one. Every request re-fetches and re-ranks from scratch against the public AppView — nothing is indexed, stored, or pre-computed.
preview the feed
not signed in — showing the anonymous, out-of-network-only preview.
verify it yourself
This whole repo is public — no submodule, but the next best thing: the
exact code that ranks this feed is one file, unminified, un-obfuscated,
right here —
sites/homemixer/src/index.ts.
The weight table quoted above is
W_LIKE/W_REPOST/W_QUOTE/W_REPLY,
the actual scoring formula is
heavyRankScore(),
and the in/out-of-network mixing + author-diversity cap is
rankAndMix().
Nothing runs server-side that isn't in that file — no model weights, no
hidden service, no env.AI call — you're reading the whole
ranker.
the honest gaps
No cryptographic verification of who's asking (see the comment on
decodeRequesterDid in the source) — the requester's DID is read
straight off the unverified JWT the Bluesky app sends, which is fine here because
every input and output is already public data and nothing gets written on your
behalf without you signing in separately. Candidate fan-out is capped for real
Cloudflare Worker latency/subrequest reasons, not habitual caution — a big account
still gets a real feed, just sampled rather than exhaustive. And because nothing's
stored, paging re-runs the whole pipeline; a seeded RNG keeps your sampled author
pool stable for a few hours so pages don't reshuffle out from under you.