Composition, not recommendation

Compose the feed.
Own the algorithm.

A headless composition engine for any collection — posts, products, videos, games, search results. BitFeed provides the primitives for sourcing, filtering, scoring, mixing, constraining and explaining. What any of it means stays yours.

What BitFeed is not

It is not a recommendation algorithm, and it does not contain one.

BitFeed has no opinion about what a feed is, what content is good, what engagement matters, what should trend, or what should appear first. It is the machinery for expressing those decisions — the same way BitGate gives an application a framework for moderation policy rather than a moderation policy. If you are looking for the part that decides your feed is interesting: you write it, as a provider, and BitFeed runs it.

One pipeline, twelve stages, all optional

A recipe that omits a stage simply skips it.

Gather
Source · Normalize
Narrow
Set ops · Enrich · Signal · Filter · Policy
Order
Score · Mix · Constrain
Deliver
Insert · Post-process

A recipe is data, not code

Which is what makes it serializable, hashable, signable, publishable, forkable and subscribable — and what lets a runtime answer “can I run this?” before running it.

{
  "spec": "bitfeed/1",
  "name": "Home",
  "sources": [
    { "provider": "nostr.following", "lane": "following" },
    { "provider": "nostr.interests", "lane": "interests" }
  ],
  "scorers": [
    { "provider": "app.interestMatch", "weight": 0.4 },
    { "provider": "bitfeed.recency",   "weight": 0.35 },
    { "provider": "bitfeed.random",    "weight": 0.25 }
  ],
  "mix": [
    { "lane": "following", "ratio": 0.6 },
    { "lane": "interests", "ratio": 0.4 }
  ],
  "constraints": [
    { "provider": "bitfeed.maxPerKey",
      "params": { "field": "creator", "max": 2, "window": 10 } }
  ]
}
Note what is absent: the viewer's interests. A preference profile lives in the composition context, never in the recipe — because a recipe is meant to be published, and sharing a feed must not mean sharing what you like.

Part of a stack, not a monolith

Each layer answers one question and requires none of the others.

Applications What does all of this mean for my product?
BitFeed How should eligible candidates be composed for this context?
BitUnlock · AdZap What entitlement does the viewer possess? Is there an eligible sponsored placement?
BitGate What policy applies to this object or action?
BitLogin Who is the viewer?
Nostr Portable events and social state.

What the engine guarantees

Four properties that hold structurally, not by good intentions.

Determinism

Same candidates, recipe, context, seed and engine version — same feed. Ties break on a hash of the seed and candidate id, so relay arrival order cannot leak into ranking. CI bans Math.random() and wall-clock reads outright.

Explanations that are true

Every ranked item carries per-provider contributions that sum exactly to the score shown. An explanation you cannot verify is decoration.

Ads cannot reach ranking

Inserted items are placed into slots, never scored into them, and run after ranking is finished. There is no code path from a bid to a scorer.

Content-type independence

Core's executable code contains no Nostr, video or product vocabulary — asserted by a test, not a convention. The same recipe shape ranks posts, listings and games.

Policy stays external

BitFeed consumes a decision and never asks why it was made. A denial removes a candidate before ranking, where no score can rescue it.

No canonical algorithm

The shipped presets are ordinary recipes over portable providers, not engine modes. Every component is replaceable, including all of them.

Try it without installing anything

The Feed Builder runs the real engine in your browser — no server, no network, no relays.

Open the Feed Builder →