Followers see your stuff: the social graph
Vibes DIY has one follow graph, owned by the platform. Follow someone once and every app you both use can build on that relationship — no app keeps its own friend list, and no app can see or change the graph beyond what you do inside it. The split to keep in mind: the platform owns WHO (follow edges, privacy, blocking, the management UI), apps own WHAT (which documents an author's followers may see).
The follow model
Follows are one-directional, like Instagram or Bluesky — never "friends":
- Following someone means you see the content they've labeled for their followers. It reveals none of your data, which is why following is low-stakes and apps shouldn't put confirmation dialogs in front of it.
- Followers are the people who see yours.
- A mutual is simply both directions at once; apps can ask for
mutuals-only visibility (see
mutualsOfbelow).
Accounts are public by default: following a public account takes effect immediately. An account flipped to private (Settings → Social) instead receives follow requests, which its owner approves or declines. Flipping public → private keeps your existing followers; flipping back to public auto-approves anything pending.
Removal is graded, and the distinction matters:
- Unfollow — stop seeing someone's follower-visible content.
- Remove a follower — stop one person from seeing yours, quietly; they can follow you again later. This is also how a private account declines a request.
- Block — the hard stop: removes the relationship in both directions and prevents any new one until you unblock. Blocking and unblocking live in Settings → Social only; apps never get a blocked list and can't unblock.
Revocation is immediate and enforced by the platform. When you unfollow, remove, or block, the affected reader loses access everywhere at once — including live-updating apps they have open. No app cooperation is involved.
The graph is per handle. If your account has more than one handle, each handle has its own followers, its own privacy setting, and its own view of the graph — your alt handle is a stranger to your main one, exactly like the access model treats it everywhere else.
Managing your graph
Settings → Social shows your active handle's Following, Followers, Requests, and Blocked lists with counts, the private-account toggle, and per-row actions (approve, decline, unfollow, remove, block, unblock). Everything an app can do, this card can do — plus the block list, which is chrome-only.
Reading and mutating the graph from an app
Inside a vibe, use the useSocial() hook from use-vibes:
jsconst { ready, following, followers, requests, follow, unfollow, approve, removeFollower } = useSocial();
- The lists are
{ handle, state: "active" | "requested" }[], always scoped to the signed-in viewer. Gate all social UI onready— it'sfalsefor anonymous viewers and during first load. - Await a mutation, then re-render from the lists: by the time the promise resolves, the hook already holds the updated snapshot. Refusals (self-follow, blocked pair, unknown handle) resolve quietly — there is no error to catch, the lists simply don't change. Don't add error toasts or polling.
approve(h)and decline-via-removeFollower(h)act on entries inrequests(private accounts only).removeFollower(h)also soft-removes an active follower.- A follow of a private account sits at
state: "requested"and grants no reads until approved — filter tostate === "active"when deciding whose content to show.
Making a doc follower-visible: the audience field
An app never queries the graph to decide visibility. Instead its access function labels a document for an audience by adding one field to a normal result:
jsif (doc.type === "favorite") {
if (doc.owner !== user.userHandle) throw { forbidden: "not owner" };
return { channels: ["share-" + doc.owner], audience: { followersOf: doc.owner } };
}
audience: { followersOf: <handle> }— that handle's followers may read the doc.audience: { mutualsOf: <handle> }— mutual follows only.- Resolution happens at read time against the live graph: a new follower instantly sees history, and an unfollow/remove/block instantly revokes — no re-saving documents, no sweeps.
- The subject is always in their own audience — authors never need a self-grant to keep reading their own follower-visible docs.
audiencecomposes with the normal channel/grant machinery: it can stand alone (an audience-only result is fully readable — the author included, via self-in-audience) or sit alongside channels and grants, which remain the way to give non-followers access paths. Keep genuinely private data on channels + grants without anaudiencefield.- Channel names starting with
~are reserved for this machinery — never write them yourself; the platform rejects them.
Copy guidelines
Say "followers can see your picks" and "people you follow" — never "friends". The relationship is one-directional and the words should say so.
See also
- The Access Model — channels, grants, roles, and why alt handles are strangers.
- Access API reference — the full
access.jscontract. - Sharing & Access guide — the owner-facing sharing UI.