Home / Blog Menu ↓

Scroll

A couple weeks ago I built my own EPUB reader called Scroll, and since then have pretty much moved off Marvin. Here’s what Scroll looks like (light and dark themes):

scroll.png

Thus far I’ve read two books using it, and while there are still a few small issues, overall I’m very happy with it. I don’t plan to release it anytime soon, but as a not-even-close-to-the-same-thing substitute, here are some notes:

  • I’d made decent enough progress with epub2pdf that it was usable, but reflowability and theme-changing are nice, and having quick navigation between books is even nicer, and printing a book to PDF in Firefox is slow, and browsers already natively support the HTML that’s inside EPUBs, so I abandoned the PDF route.
  • Scroll (after both the noun and the verb) is a PWA without a backend. It’s actually just static HTML files: I wrote a script that concatenates all the HTML in an EPUB into one long HTML file, with some processing to fix links and wrap things and bake the table of contents out. Then there’s a little bit of vanilla JS for the reader functionality (saving the debounced current scroll location to localStorage (I wish Safari supported scrollend), restoring it on the pageshow event, calculating pagination, jumping to pages, switching themes, etc.), and another vanilla JS file listing the current books (so that I don’t have to re-build all the other book files when I start reading a new book).
  • While I said “pagination” above, I’m not actually chunking the book into pages; I’ve chosen to stick with vertical scrolling for now instead of horizontal paging, primarily because being able to make sub-page progress is nicer than I realized. That said, I still want to know how many “pages” I’ve read, so I use the scroll percentage (scrollTop divided by scrollHeight, super simple) multiplied by a rough heuristic of 1,200 characters per page, ignoring whitespace. It’s not perfect but it’s good enough for my needs.
  • I added a slight blur to the text so that it feels a little less digital. For now I’ve opted against a background image, but I may change my mind about that.
  • Whenever I add/remove a book, I copy the baked files to a private directory on my server
  • I’ve saved the root HTML file (which is just a list of the current books, loaded via JS) to my home screen as a PWA