Revisiting My Reading List

2026-05-30

The best kind of weekend project takes just a few scattered hours while solving a supremely pedantic annoyance. That's the story of my hand-rolled book-tracking replacement.

The idea stemmed from a discussion with friends, where a conversation about books transitioned into how we keep track of our respective lists.

Unlike Letterboxd, which solves movie-tracking with a sublime grace, every reading platform kind of stinks. Goodreads is a vehicle for advertisement that has languished under Amazon's stewardship. Storygraph is the Next Best Thing, but is (unfortunately) supremely ugly. Margins looks neat but caters too heavily to the obsessive-impulsiveness of the BookTok crowd. Hardcover gives me whiplash every time it swaps between open source fantasy and legitimate product.

I don't mean to be too hard on these products, making a social book site is a surprisingly hard endeavor. The world of editions, publishers, and ISBNs is an absolute mess! But look, I just need a place to keep a list of books that I can share with my friends. I don't need recommendations, I don't need reviews. I don't use these sites to find my next read.

And so, taking a page out of Tom MacWright's book, I absorbed my reading list into this very site.

I keep my list as a YAML file that is easy enough to keep updated as I rotate through books:

- title: "A Wild Sheep Chase"
  author: "Haruki Murakami"
  status: "read"
  started: 2026-04-22
  finished: 2026-05-05
  isbn: 9780375718946

I compile this YAML file into two different file types. The first is the HTML template that becomes /reading. The second is an Atom feed that I use to push updates to a Discord channel.

That second point is inspired by Filmlinkd, which our Discord server uses to post Letterboxd activity into a text channel. Since my books are tracked in a YAML file, I need some mechanism for tracking changes and triggering a message. That mechanism is an Atom feed and a Cloudflare Worker.

Atom is a great fit for this job. Each book entry has a natural ID formed by it's ISBN, which I form into an OpenLibrary URL: https://openlibrary.org/isbn/9780375718946. An entry's updated-at field is either the started date or the finished date. A book transitioning from "reading" to "read" will naturally have a later finished timestamp, indicating an update.

The update ends up in the Discord server via a Cloudflare Worker. The worker reads the Atom feed on a periodic basis (every 30min) and looks for updated items (by comparing the new read to the cache in Cloudflare KV). If it finds an update, it forms a message and posts it to the server via a webhook.

Weekend accomplished.

Check out the source: https://git.sr.ht/~mgmarlow/reading-list-poster.