Weevil
Weevil is my personal book tracking service — a place to keep a record of books I’ve read, want to read, or am currently reading, without depending on a third-party platform like Goodreads.
I wanted full ownership of my reading data. Weevil runs on my own infrastructure, stores everything in a database I control, and exposes it through an API I wrote. It also gave me a realistic project to explore event-driven architecture with Kafka, asynchronous enrichment pipelines, and a WebAssembly frontend in Go.
Weevil is a personal book tracking service — a place to keep a record of books I’ve read, want to read, or am currently reading, without depending on a third-party platform like Goodreads or Storygraph.
Why I Built It
I wanted full ownership of my reading data. Existing platforms are convenient but come with trade-offs: lock-in, privacy concerns, and the ever-present risk that a service you rely on changes or disappears. Weevil runs on my own infrastructure, stores everything in a database I control, and exposes it through an API I wrote.
It also gave me a realistic project to explore a few technologies I wanted to spend more time with: event-driven architecture with Kafka, asynchronous enrichment pipelines, and a WebAssembly frontend in Go.
What It Does
At its core, Weevil is a book catalogue:
- Import books from a Goodreads RSS export, or search for them by title, author, or ISBN
- Enrich each entry automatically with metadata from Google Books and Open Library — cover images, descriptions, page counts, categories, publisher information
- Store everything in PostgreSQL with raw API responses archived to object storage for reference
- Browse the catalogue through a browser-based SPA or a command-line client
Design Philosophy
Weevil is intentionally a personal, self-hosted service. It has no multi-tenancy, no authentication layer, and no ambition to scale beyond a single user. That constraint keeps the codebase focused: the problem is well-scoped, and every design decision can be made with a known workload and a single consumer in mind.
The event-driven architecture is slightly over-engineered for the problem, but that’s part of the point — it’s a learning project as much as a practical tool.
Tech Stack
- Backend: Go, ConnectRPC, PostgreSQL
- Messaging: Kafka (Redpanda in local development)
- Object storage: MinIO (S3-compatible)
- Frontend: WebAssembly SPA written in Go using go-app
- Metadata sources: Google Books API, Open Library
For a deeper look at how the pieces fit together, see ARCH.md.