Kindle Agent
A private, invite-only library for my family and friends: search free sources for a book or an audiobook, and get it on a Kindle or straight onto your phone.
The problem
I read on a Kindle, and so do my mom and my sister. Getting a book on there means a weeks-long Libby hold or Amazon's price, and Send-to-Kindle is a manual hunt-download-email loop where half the EPUBs you find fail silently. Once other people started using it, a second problem showed up: when it broke, nobody could tell me what happened. They just stopped getting books.
My hypothesis
Put a search box in front of every free and self-hosted source, wire it into Amazon's Send-to-Kindle pipe, and the whole dance collapses to one tap. The bet: aggregation plus reliable formatting is the product, not any single source.
What I built
An invite-only Next.js app with magic-link auth. One search fans out across five sources in parallel — Standard Ebooks, Gutenberg, Open Library, LibGen, and a self-hosted torrent bridge — deduped into a single ranked list. The pick is repaired to spec and delivered. Delivery has two modes, because not everyone reading is on a Kindle. Kindle users get the file emailed. Everyone else downloads it straight to the device, which turned out to be the harder path — an iPhone home-screen app has no download manager, so a JavaScript blob download silently does nothing. That path navigates the page to a GET route instead, and iOS then offers Open in Books or Save to Files. It has grown well past search-and-send. Audiobooks run as a deliberately separate subsystem, since a 700MB .m4b breaks every assumption the ebook path makes. Want to Read watches for a book you couldn't get yet and delivers it the moment a copy appears. Followed Book Lists tracks what real book clubs are reading each month and tells you when a new pick lands. A shared EPUB cache means the second person to want a book gets it instantly.
What broke
Amazon rejects almost every EPUB on the internet with an opaque E999 error. I burned time on AZW3 and MOBI before finding the fix: rewrite the file to spec, which is the actual product. Magic links kept dying to Gmail's link prefetcher, so the token consume had to go POST-only. The failure I didn't predict was legibility. Search would return nothing and there was no way to know whether the book didn't exist, a source was down, or the query was worded wrong. Three books failed in one day for three different reasons, and the telling one had a perfectly spelled title whose file simply has no author in the name, so including the author is what lost it. Searching one way and calling that the answer was the bug.
What I learned
When other people depend on your side project, the work shifts from adding features to telling the truth about failures. Every empty search now records what each source actually did, and the admin page will name which LibGen mirror timed out. A search tries the title with the author, then the title alone, then the title without its subtitle, then the author alone. The constraint I'm most glad I kept: no LLM or search API key anywhere in the product. Anything that needs open-ended reasoning runs as an MCP server on the user's own Claude, so the app stays deterministic, free to run, and never breaks because a key expired.
If I kept going
Per-job fetch tokens so a leaked bridge token can't pull any file. Better onboarding for the one manual step every user still does themselves: allowlisting the sender on Amazon. And a real answer for the books no source has, which is still the honest gap.
What was built
Frontend & Auth
Invite-only, installable as a home-screen app
- Next.js 16 / React 19
- Tailwind CSS 4
- Magic-link auth, 30-day sessions
- Upstash Redis
- Versioned What's New splash
Search Aggregation
Five sources in parallel, one ranked list
- Standard Ebooks
- Project Gutenberg
- Open Library
- LibGen
- Self-hosted torrent bridge
- Four-way query fallback on a miss
Delivery
Kindle email or direct to device
- EPUB rewritten to spec (the E999 fix)
- Resend to a per-user Kindle address
- In-place GET download for iOS home-screen apps
- Shared EPUB cache for repeat books
- Per-user send cap
Audiobooks
A parallel subsystem, not a bolt-on
- Download-only, a Kindle can't play one
- 100MB to 1GB .m4b or bundled .mp3
- Its own queue, routes, and progress UI
- Per-device save instructions
Discovery
Finds books you're not searching for
- Want to Read auto-delivers on availability
- Followed Book Lists tracks club picks
- Monthly pick notifications
- Reading status, ratings, and stats
Reliability
Every failure has to be answerable
- Per-source outcome on every empty search
- Named LibGen mirror failures
- Live bridge health check
- Per-person admin drill-down
- Resend bounce webhook




