About

Hello! I'm @jola.dev and I made shelf.cafe after being inspired by bubbles.town. I wanted to see what the same thing would look like, built on top of atproto.

shelf.cafe aggregates content from a list of blogs, based on the bubbles.town list which in turn is a combination of many blog rings and directories, by polling their feeds. Whenever new content is detected, it's automatically added to new. It is now also possible to submit links directly.

atproto what?

shelf.cafe publishes items to atproto, under the cafe.shelf.item lexicon. What you see on the front page is the content rendered from the AppView. You can vote on items by logging in through your Bluesky account, or any other atproto account such as Eurosky, pckt.cafe, tangled.sh, and many others.

Note that currently the AppView does not discover content created outside the app, but that's coming. I also want to add features around auto-discovering content posted under the standard.site lexicon.

Themes

Don't like the colors? If you log in you can select from a set of different themes on the login page. This preference is recorded in local storage. You can also specifically opt into dark or light mode.

A widget for your blog

You can include a widget on your blog to show vote count and link things up. If your blog post is published already, it'll look something like 2 ▲ on shelf.cafe, linking to the item on this site. If it's not published, it'll say ▲ post on shelf.cafe and links to the submission form with the URL pre-filled.

<!-- Add this on your page where you want the widget -->
<div class="vote-on-shelf"></div>

<!-- Add this in <head> or at the bottom of your HTML document -->
<script src="https://cdn.shelf.cafe/scripts/widget.js?vsn=1" defer></script>

How shelf.cafe fetches content

The app polls feeds for new content on a regular basis, recording posts as seen as it goes, and publishes new items when discovered. It respects /robots.txt, as well as Last-Modified and ETag headers. If a blog disallows fetching the feed, or otherwise fails requests, the blog is marked as disabled and the app will stop polling it. Retries after failures use exponential backoff with jitter over ~24h.

If you wish to disallow shelf.cafe from fetching your feed, add

User-agent: shelfbot
Disallow: /rss.xml # or *

to your /robots.txt, or contact me at hello@shelf.cafe.

Algorithm and moderation

/new has no algorithm applied to it and will always show new posts as they come in. The landing page, aka "top", does apply a ranking to each item based on its number of votes, with a strong recency bias. The goal is for the front page to have mostly new content each day, although that depends on activity. Here's the actual algorithm:

Score = Votes ^ 0.8 / (Age + 2) ^ 1.8

Or in plain language: each vote on an item is less powerful than the one before, dampening the effects of a single item getting a massive amount of votes. That is divided by the age, also with a modifier that makes it more influential as time passes. Combined it means that newer content eventually beats out older, and we get a nice fresh front page.

shelf.cafe subscribes to four labelers at the time of writing this: Bluesky Moderation Service, Northsky Moderation, Blacksky Moderation, and Skywatch Blue. A subset of labels offered by these services are used to apply limits to the content on the website. This can change at any time. shelf.cafe can also apply local limitations where required.

Feedback

Please feel free to tag @shelf.cafe or @jola.dev on Bluesky, or send an email to hello@shelf.cafe, and share any feedback that you have!