Paperless
A reader that turns PDFs and EPUBs into pages that actually fit your screen. Local-first, works offline.
Labels can be wrong, but they can't put words in an author's mouth.
- Year
- Stack
-
- Next.js Next.js
- React React
- TypeScript TypeScript
- TailwindCSS TailwindCSS
- Vercel AI SDK Vercel AI SDK
The idea
I read a lot of books as PDFs, and every PDF reader I tried showed me either a tiny fixed page or a wall of broken text. That’s because a PDF is a print layout, and a phone isn’t paper.
Paperless doesn’t show the print layout. It reads the file’s structure (its outline, headings and fonts) and sets the text again as pages the size of your screen. Each page is one screen of text and ends in a large Next button that names the next chapter.
Keeping what print got right
Most of the work went into the details a book loses when you just pull out the text:
- Real chapters. They come from the PDF’s own outline, matched to the headings on the page.
- The print details, kept. Drop caps join their word again, epigraphs keep their credit line, and italics come from the font names in the file.
- The print noise, gone. Running heads and page numbers are dropped. Praise and copyright pages stay hidden until you ask for them from the contents.
- EPUB and Gutenberg. The browser unzips an EPUB and reads it. Free Gutenberg books come in through their HTML editions, which already mark chapters, quotes and verse.
How the AI stays honest
The model never writes the book. For each page it gets the paragraphs with ids, and it answers with labels only: this is a heading, that’s a quote, that’s a stray page number. Both the server and the browser then check the answer. The checks drop unknown ids and reject quoted passages that don’t match the page word for word. Every page the model touched keeps a “Show original” link.
An earlier version asked the model to rewrite each page as clean text. A rewrite can paraphrase, or come back in a different language than the book’s, and the reader has no way to tell. So I switched to labels.
The same rule covers Discover, where you can search Open Library and Project Gutenberg or describe what you feel like reading. Paperless checks every suggestion against Open Library first, so a book the model made up never shows.
Your books stay yours
Nothing is uploaded and there are no accounts. The library lives in IndexedDB, the app works offline once installed, and a backup is one file you own.
Without any keys the reader works fully. Readers can add their own Gemini key, and it stays in their browser. The site’s own key has a daily cap, and each person gets a smaller hourly allowance.
Testing it without anyone’s books
The Playwright suite runs against the production build on an iPhone viewport and a desktop one, the same way CI runs it. The tests make their own books: a PDF printed by the browser, an EPUB zipped in memory and a Gutenberg-style page. No copyrighted text is in the repo. The AI is mocked with an answer that contains a made-up passage, and the test passes only if the reader rejects it.