I Track My Reading with GitHub Issues

Most people use Goodreads to track books. I use GitHub Issues.

It didn't start this way. Here's how I got here.

Version 1: The JSON File

A books.json file in my website repo with 33 books I'd read:

{
  "title": "Norwegian Wood",
  "author": "Haruki Murakami",
  "image": "https://m.media-amazon.com/images/...",
  "rating": 4.3,
  "pages": 296
}

Every time I finished a book, I'd open the file, add an entry, find the cover image URL from Goodreads or Amazon, look up the ISBN, and commit. It worked - for about two months.

Then I built a shell script that took a book title and tried to find the cover image and metadata from Open Library. Semi-automated, but still required hand-holding - I'd run the script, verify the cover looked right, paste the ISBN, fix the author name if it came back in Japanese characters. Better than fully manual, but still friction.

The real problem: I'd finish a book on my commute, think "I should log this," and by the time I got to my laptop it was forgotten.

Finding Anand's Setup

Then I found anandchowdhary.com/books. Anand Chowdhary had built something clever - a GitHub Action called bookshelf-action that turned GitHub Issues into a book tracker. Open an issue with the book title, and the action fetches metadata from Google Books, adds labels, and generates a JSON API.

GitHub Issues as a UI means I can add a book from my phone in 10 seconds. The data lives in a repo I own. No database, no API keys, no third-party dependency.

I forked the repo, set it up, created a test issue... and nothing happened.

What Was Broken

Three things:

1. Google Books API died. Sometime in late 2024, Google set the unauthenticated quota to zero. Every request returned 429. The action's search silently failed and posted "I couldn't find this book" on every issue.

2. Node 16 deprecation. GitHub Actions deprecated Node 16, then 20. The action's dist/ was compiled years ago and silently crashed on Node 24 runners.

3. The config blocked me. The .bookshelfrc.yml had users: ["AnandChowdhary"] - only his username was allowed to create books. My issues were processed and immediately skipped.

Making It Work

I forked to bhaumikmistry/bookshelf-action and rebuilt it.

Open Library as the primary source. Free, no API key, reliable. Tries Google Books first (in case they restore free access), falls back to Open Library.

3-tier book resolution. Instead of just searching by title, I added precision:

  1. Paste an Open Library edition ID in the issue body (e.g. OL57519135M) β†’ exact match
  2. Paste an Open Library URL β†’ extracts the ID
  3. Just the title β†’ searches by title + author

Without this, "Norwegian Wood" returns a woodworking guide instead of the Murakami novel.

Comment commands. The original only tracked progress. I added:

CommentWhat happens
50%Progress bar updates
150/300Calculates percentage from pages
100%Marks complete, auto-closes the issue
abandonedMarks abandoned, closes
rating:4.5Sets my rating
category:favorites,2025Tags the book
cover:https://...jpgOverrides cover image

No more locked issues. The original locked issues after creation (to prevent random comments). I removed that so I can always come back and add a rating or update progress - even months later.

How It Works Now

Open issue: "The Story Collector by Evie Gaughan"
Body: OL47040160M
                    ↓
Action fires β†’ fetches from Open Library
                    ↓
Bot comments with cover, ISBN, pages, description
Labels: author, year, decade, language, publisher
                    ↓
I comment "110/358" β†’ title becomes "(31%)"
                    ↓
I comment "100%" β†’ issue closes automatically
                    ↓
api.json rebuilds β†’ website updates within 5 minutes

Website Integration

My library page fetches api.json directly from GitHub:

https://raw.githubusercontent.com/bhaumikmistry/books/main/api.json

Next.js revalidates every 5 minutes. Open issues show in "Checked Out from Library" with progress bars. Closed issues show in "Checkout History." No database, no backend.

The JSON:

{
  "title": "The Story Collector",
  "authors": ["Evie Gaughan"],
  "image": "https://m.media-amazon.com/...",
  "pageCount": 358,
  "state": "reading",
  "read": 31,
  "abandoned": false,
  "rating": null,
  "userCategories": ["2026"]
}

Backfilling 33 Books

I had 33 books in my old books.json that needed to migrate. I wrote a script that:

  1. Looked up each book on Open Library by ISBN (or title+author)
  2. Found the correct edition ID
  3. Created a GitHub issue with the title and edition ID in the body
  4. Waited 35 seconds between each (so the action could process them without queueing chaos)

19 minutes later, all 33 books were in the system with covers, ISBNs, and metadata auto-populated. Then a second script added my ratings and categories as labels.

A few hiccups: CJK author names (ζ‘δΈŠζ˜₯ζ¨Ή) crashed the label slugifier, one Open Library edition resolved to a Canadian law textbook instead of "The Psychology of Money", and Google Books rate-limited the IP after the first test. All fixable.

What I Learned

Have a fallback for third-party APIs. Google Books worked for years, then didn't. Open Library saved the project.

GitHub Issues is a good UI for structured data. Labels, comments, open/close state. It's a mini-database with a free frontend.

Own your data. A JSON file in a repo I control. If I switch frameworks, the data comes with me.

The 30-second test. If I can't add a book in under 30 seconds from my phone, I won't use the system. GitHub Issues passes. Editing JSON in VS Code does not.

Stack

LayerWhatCost
UI for adding booksGitHub Issues (web + mobile)Free
Book metadataOpen Library APIFree
AutomationGitHub Actions (custom fork)Free
Data storageapi.json in a public repoFree
Website renderingNext.js fetch with revalidationFree
Cover imagesOpen Library + Goodreads fallbackFree

Repos: bhaumikmistry/books and bhaumikmistry/bookshelf-action.