Feed and hearth picks
The feed answers “What are my people up to?” It is yours alone (your seen state, your circle choice), it mixes in suggestions to visit people Homestead can’t see, and it ends.
What’s in your feed
Section titled “What’s in your feed”With All selected, the feed shows people in every circle you have “In my feed” switched on,
plus people who aren’t in any circle. Pick a circle pill to see just that circle. Your choice
is kept in the address (?circle=) and remembered on that device.
A moment is a candidate if it’s a live story, or another kind of post from the last 14 days.
How it’s ordered
Section titled “How it’s ordered”Three things decide where a moment lands:
- How recent it is. A post loses half its weight every 18 hours.
- How close you are. “Closest” people count fully, “Close” a bit less, “Following” less again.
- Whether it’s a live story. Stories get a small boost, because they disappear.
Then a diversity pass stops one chatty person from taking over: never more than 2 moments in a row from the same person, and never more than 4 from one person in any 20.
Hearth picks
Section titled “Hearth picks”A hearth pick is a card that suggests a visit: “It’s been a while since you visited Grandma Noi. Say hi on LINE?” Homestead shows one when it can’t, or doesn’t, show someone’s posts:
| Reason | When |
|---|---|
| Closed platform | The person has an account on a closed platform and no account that’s fetching fine. |
| Source unavailable | No account is fetching fine, and one needs an agent, needs a login, has errors, or is agent tier with no agent connected. |
| Quiet | An account works, but there’s been nothing for 7 days and you haven’t visited in 3. |
The longer since your last visit, the more likely a person is to come up, up to a limit. Closer people come up more often. Someone you visited in the last 24 hours doesn’t come up at all.
Each card has three choices:
- Visit on LINE (or the right app) records a visit and opens the app.
- I checked in records a visit without opening anything, and the card says “Nice!”.
- Not now snoozes the person for 3 days.
For WeChat, the buttons are Copy WeChat ID and Open WeChat, because WeChat has no profile links.
The same picks all day
Section titled “The same picks all day”The picks are drawn at random, but the draw is seeded by you, the circle and today’s date. You see the same suggestions all day, not a new set on every refresh. Shuffle suggestions (long-press refresh, or the menu) draws again.
A pick appears after every 5 to 7 moments. If you have fewer than 3 unseen moments, up to 3 picks go at the top. If nobody in the feed has fetchable posts (a family that only uses LINE and WeChat), the feed is only picks. There are at most 6 picks per feed.
The story rail
Section titled “The story rail”The row of faces at the top, in this order:
- People with unseen live stories (full gradient ring).
- People with other unseen moments from the last 24 hours (thin ring).
- Up to 3 visit bubbles (dashed ring with a platform badge). They match the first hearth picks. Tapping one opens a small sheet with Visit, I checked in and Not now.
- People whose moments you’ve already seen in the last 24 hours (grey ring).
Tapping a face opens the story viewer. Swipe between people; tap left and right to move between moments; hold to pause.
Seen, and caught up
Section titled “Seen, and caught up”A moment counts as seen when it’s on screen in the story viewer for 1 second, or when a feed card is at least 60 % visible for 1 second. Agents never mark anything seen.
When you’ve seen every unseen moment, the feed shows You’re all caught up. Below it, an earlier section shows up to 30 moments you’ve already seen from the last 3 days. Then the feed stops. There’s no infinite scroll, no streaks and no red badges.
New posts that arrive while you’re reading don’t shuffle the page; they show up on the next refresh.
Recently visited
Section titled “Recently visited”When the Firefox companion saves new posts from a profile you visited in the last 24 hours, a Recently visited strip appears at the top of the feed, newest first, up to 8 people. Each member chooses whether their visits are shown to the household. The web strip is Coming in 1.0 (W-12).
The formulas, for the curious
All ranking code is pure functions in
server/internal/feed/,
specified in docs/06-feed.md.
Moment score:
score(moment) = recency × closeness × kindBoost
recency = 0.5 ^ (ageHours / 18) # half-life 18 hourscloseness = {1: 1.0, 2: 0.7, 3: 0.45}[person.closeness]kindBoost = 1.25 if kind == story (live) else 1.0Unseen moments sort by score, then by publish time, then by id.
Hearth pick weight:
daysSinceVisit = days since your last visit (never → 14)staleness = min(daysSinceVisit / 7, 3.0) # 0 … 3weight(p) = closeness(p) × (0.25 + staleness) × reasonFactorreasonFactor = {closed_platform: 1.0, source_unavailable: 0.8, quiet: 0.6}Picks are sampled without replacement, weighted by weight, with a PCG random generator
seeded by:
sha256(memberId | circleId or "all" | localDate | shuffle)The gap between picks is drawn from feed.hearth_pick_every (default 5 to 7) with the same
generator. The feed cursor carries the seed and a snapshot time and is HMAC-signed, so pages
stay stable while new moments arrive.