
Bookshelf
A self-hosted ebook library that runs on Cloudflare R2 or a local Node server, with in-browser EPUB and PDF readers and per-profile reading positions.
What is Bookshelf?
Bookshelf is a self-hosted library for the ebooks you already own. It is a single server-rendered application that lists the books in your collection, filters them through a search box, serves downloads, and reads them in the browser through dedicated EPUB and PDF readers. There is no database — everything is read from object storage, which means backups are just the storage bucket.
The app ships with two interchangeable storage providers: a Cloudflare Worker backed by R2 object storage, or a plain Node server backed by a directory on disk. The same code drives both — only the storage adapter changes.
Key features
- One-page shelf. Books appear as a single server-rendered grid with covers, filterable through a search box and a Continue button that jumps straight back into the book being read.
- In-browser readers. EPUB and PDF each have their own reader. EPUB renders as a paginated reader in the browser; PDF is served with a native-style viewer.
- Profiles. Each reader picks a profile from a switcher, and reading positions are stored per profile so housemates or family members do not overwrite each other.
- Two storage providers. Cloudflare R2 via a Cloudflare Worker, or a local filesystem via a Node server. Docker is supported for the Node path.
- No database. The library is regenerated from the source files each time the sync tool runs, so there is nothing to migrate or back up beyond the storage itself.
- Public-domain demo.
npm run demopopulates the library with nine generated public-domain titles so the shelf can be tested or screenshotted without supplying your own ebooks.
Self-hosting
The fastest path is Docker: put EPUB and PDF files in a books/ directory and run docker compose up. The image includes the cwebp and pdftoppm image tools so covers come out right without installing anything on the host. A named library volume holds the published books, profiles, and reading positions — it is the only thing to back up.
Without Docker, Bookshelf runs on Node 24 or newer on any Unix-like system. Set bookshelf.config.json to point at a directory, run npm run sync -- --create, then npm start.
On Cloudflare, run npm run sync -- --create against an R2 bucket, then npm run deploy to ship the Worker. The repo includes checked-in wrangler.jsonc and bookshelf.config.json that need to agree about which bucket holds the library — the sync tool checks this before uploading.
A BOOKSHELF_READ_ONLY=1 environment flag tells a public instance to stop accepting writes while continuing to serve, useful for sharing a library without exposing the management interface.








