What a Shelf Actually Is
A shelf looks like a container. It is not. "For You", "Queue", "Archived", "Korea" — none of these hold articles. Each is a function that takes the store plus the projected reading state and returns an ordered list, computed the moment someone asks. Nothing is filed into a shelf and nothing is removed from one; the inputs change and the function returns something different.
Getting this straight early is what keeps the design coherent later, because it settles a question that otherwise gets answered differently in every feature: where does a rule live? If "disliked articles do not appear here" is a property of the shelf function, it applies consistently and can be changed in one place. If it is implemented by deleting rows, it has become irreversible, and the next feature that wants disliked articles — a settings screen showing what you muted, say — has nothing left to show.
Render-Time Rules Compose
Once shelves are functions, the interesting behaviors become composable steps in a pipeline rather than special cases. A shelf query over-fetches from the store, then passes the rows through a sequence: collapse repeats of the same story, drop muted terms, promote pictures into the visible region, trim to the requested size. Each step is independently testable and independently removable.
The alternative — baking each of these into SQL, or worse into the ingest path — buys a little speed and costs you the ability to reason about any of them. A rule applied at ingest is a rule you cannot turn off for one shelf, cannot explain to the reader, and cannot change your mind about without a migration.
Say What You Did
A projection that quietly reorders or removes things is a black box wearing a list's clothes. Every step that changes what the reader sees should report a count alongside the rows: this many repeats collapsed, this many muted, this many promoted. The client can then show it, and the reader can tell the difference between "there is nothing here" and "there is plenty here and I filtered it."
The Freedom You Get Back
The payoff for all this discipline is that projections become cheap to be wrong about. A ranking function that turns out to over-weight something is a bug you fix and recompute — no migration, no backfill, no data loss, because nothing about the fix touches the log. That is the actual reason to keep truth and presentation separate: not purity, but the ability to change your mind about presentation as often as you need to.