Goread2 - Chapter 1: The Beginning
This is the first in a series of posts wherein I attempt to recount the history of Goread2 as it approaches a state in which I might actually try to share it more broadly.
I’ve long missed Google Reader, which Google killed in 2013. Over the years, I tried both Feedly and Reeder and was left wanting and/or overwhelmed by product management run amok. I was aware of an open source project called GoRead which attempted to recreate the Google Reader UX; but it had fallen by the wayside and was no longer maintained.
Early in 2025, at work event, I saw a demonstration of an AI-powered coding agent that looked intriguing. When Claude Sonnet 4 was released in May, suddenly “promising” switched to “I need to learn as much as I can about this as fast as I can”. I became a regular Claude Code user and my Claude Pro subscription shortly followed.
By July, I was using Claude Code often enough that I thought resurrecting GoRead might be an interesting side project. At first, I thought I could clone and modernize the GoRead project; but Claude talked me out of it and we started from scratch.
And yeah, when I say “we” in these posts, I’m referring to Claude Code being prompted by me. It feels just as weird to write as it does to read.
We made the first commit on July 26. It was 15 files and about 2,500 lines of code: a Go backend using the Gin web framework, a vanilla JavaScript frontend, an HTML template for the layout, and database support for both SQLite (for running locally) and Google Cloud Datastore (for eventual deployment on App Engine). The Database interface that lets the same code talk to either backend was in this first commit, because App Engine deployment was never an afterthought. From the start, I wanted this to be a real, running thing on the internet and I wanted to see if I could use Claude Code to build an actual product.
That said, at first the data model was simple. A Feed had a URL, a title, a description, and timestamps tracking when it was created and last fetched. An Article had a feed ID, a URL, a title, content, and an author. The Database interface had nine methods — AddFeed, GetFeeds, DeleteFeed, AddArticle, GetArticles, GetAllArticles, MarkRead, ToggleStar, UpdateFeedLastFetch — and that was it. Notably absent from all of this: any concept of a user. So that wasn’t going to scale.
On August 2, we added multiuser support in this commit. The diff was 28 files and over 4,000 new lines of code. Everything that was implicit in the single-user design had to be made explicit: which user’s feeds are these? Which user starred this article? Who is allowed to see what? We added a Google OAuth 2.0 authentication flow, along with HTTP-only session cookies, session management, and auth middleware wrapping every API endpoint. The Database interface grew from 9 methods to nearly 40. user_feeds and user_articles join tables appeared, giving each user their own independent view of the world. We also implemented the first pass at a test suite: unit tests for the database layer, auth system, and feed service; and integration tests verifying that one user could not see another user’s data.
Looking at the two commits side by side, what strikes me is how much architectural decision-making was packed into that six-day gap. The dual-database abstraction that was already there made adding multi-user support much easier because the same interface that swapped SQLite for Datastore could absorb the new user-scoped methods without breaking the shape of the code. The decision to build for App Engine from day one meant the deployment target was already understood when we made the authentication choices.
I’m also glad that we didn’t skimp on the tests at this stage. Obviously once you have multiple users, every piece of data needs an owner, and the places where you forgot to check ownership become security bugs rather than minor annoyances. I felt that integration tests, particularly the ones verifying user data isolation, were necessary even at this early stage.
By mid-August, GoRead2 had gone from a personal weekend project to something that could maybe possibly be used by strangers. The next step was to actually make it available on Google Cloud. That’s when things started getting complicated.
Next up: Deployment Hell.