bookshelf README

The project's README from github.com/murerkinn/bookshelf. As one markdown file: README.md.

Bookshelf

CI

A self-hosted library for the ebooks you already own. Put your EPUBs and PDFs in a folder, publish them, and read them in any browser — or on your Kobo, through the OPDS catalog.

The shelf: a searchable list of books with covers, a profile switcher, and a Continue button on the book being read

Run it as a Cloudflare Worker over R2, or as a Node server over a directory on your own machine. Both use the same code and the same library.

📖 Full documentation

Try it in a minute

You'll need Node 24 or newer and a Unix-like system. Windows isn't supported — the sync tool looks for its image tools with which.

git clone https://github.com/murerkinn/bookshelf.git
cd bookshelf
npm install
npm run demo

npm run demo writes nine generated public-domain books into books/ — eight EPUBs and a PDF, so both readers are one click away. It downloads nothing. Then publish and run them by whichever route below.

The checked-in bookshelf.config.json points at Cloudflare R2, so npm run sync goes there unless you change it. For a local look, switch it to the filesystem provider first:

// bookshelf.config.json
{ "storage": { "provider": "fs", "directory": "shelf-data" } }

Set up your own

Put your books in books/, then pick where the library should live.

With Docker

The shortest route, and the image ships the tools that make covers.

mkdir books && cp ~/Downloads/*.epub books/
docker compose run --rm sync --create
docker compose up -d

Your shelf is on http://localhost:3000. Sync flags pass through, so docker compose run --rm sync --force works as it does locally.

Back up the library volume — it holds your published books and your reading positions. To bind-mount a host directory instead, chown it first:

chown -R 1000:1000 /srv/bookshelf

On a machine you own

No account anywhere.

// bookshelf.config.json
{ "storage": { "provider": "fs", "directory": "shelf-data" } }
npm run sync -- --create
npm run build
npm start -w @bookshelf/app

More in the filesystem provider.

On Cloudflare

You'll need a Cloudflare account. Edit bookshelf.config.json and apps/bookshelf/wrangler.jsonc so they name your bucket and Worker — if they disagree, the sync tool stops before uploading.

npx wrangler login
npm run sync -- --create
npm run deploy

More in the R2 provider.

Before you commit a library to it

There is no authentication. Anyone who can reach your shelf can download every book in it, and pick any profile while doing it. The OPDS catalog makes it machine-enumerable as well. Put it on a network you trust, or behind something that asks who's calling.

Nothing is encrypted. Your library is stored in the clear, and object keys are slugified titles — a listing of your storage names your shelf. With the filesystem provider you can keep it on an encrypted volume today.

Two devices reading one profile at once is last-write-wins.

What's missing has the full list.

Configuration

variable what it does
BOOKSHELF_READ_ONLY set to 1 and storage keeps serving but stops accepting. Profiles can't be added, renamed or deleted, and reading positions stay in the browser. Set this on anything strangers can reach
BOOKSHELF_PROVIDER override the provider the build was made with
BOOKSHELF_DIRECTORY override where the filesystem provider looks
BOOKSHELF_SITE_URL the public address, for link previews and canonical URLs. Set it behind a proxy that doesn't say so

Everything else lives in bookshelf.config.json — see publishing.

Commands

All from the repository root.

npm run dev          # local dev server, against the local R2 bucket
npm run sync         # build the library and publish it
npm run build        # build every workspace
npm run check-types  # typecheck every workspace
npm run preview      # build + run the Worker locally
npm run deploy       # build + deploy to Cloudflare Workers
npm test             # the test suite
npm run lint         # biome, across the repo

npm run cf-typegen -w @bookshelf/app regenerates cloudflare-env.d.ts after you edit wrangler.jsonc.

Documentation

Published at https://murerkinn.github.io/bookshelf/.

Publishing a library the sync tool, its flags, and covers
The library format what ends up in storage, and what to back up
Storage providers choosing where your library lives
Cloudflare R2 setup, deploying, publishing locally
Filesystem your own machine or a VPS
Profiles who is reading, and where they got to
Reading in the browser the readers and their controls
The OPDS catalog reading on a Kobo, a Kindle, or any OPDS client
Architecture for working on the code
What's missing limitations, and what's planned

Contributing

See CONTRIBUTING.md. In short: Node 24, npm install, and npm run lint, npm run check-types and npm test before you push. Say what you verified — the tests reach the packages and the app's service layer but not its pages.

Storage providers are the extension point, and yours doesn't have to live here. A package published by anyone can be installed and named in the config.

License

MIT — see LICENSE.

That covers the code in this repository. The app and the Docker image also ship other people's, under their own terms, listed in THIRD-PARTY-NOTICES.md.

None of it says anything about the books you put in a library built with it, whose copyright is between you and their publishers.

bookshelf (murerkinn/bookshelf)

Searching Database…

Что это?Bookshelf — это селфхостед-библиотека для электронных книг, которые у вас уже есть. Вы кладёте EPUB и PDF в папку, публикуете их и читаете в браузере или на Kobo через OPDS-каталог.
Ему нужна база данных или отдельный бэкенд-сервис?Нет. Он работает целиком на объектном хранилище: либо как Cloudflare Worker поверх R2, либо как Node-сервер поверх обычной папки на вашей машине — и вообще без базы данных.
Как его запустить?Склонируйте репозиторий, запустите 'npm run demo' для генерации примеров книг, затем опубликуйте и запустите через Docker или локальную файловую систему, либо разверните на Cloudflare, отредактировав bookshelf.config.json и wrangler.jsonc так, чтобы они указывали на ваш R2-бакет и Worker.
Что нужно установить перед началом?Node 24 или новее и Unix-подобная система; Windows не поддерживается, потому что инструмент синхронизации вызывает утилиты для работы с изображениями через 'which'. Если развернёте на Cloudflare, дополнительно понадобится аккаунт Cloudflare для R2 и Workers.
Безопасно ли просто выложить мою библиотеку в сеть как есть?Нет — аутентификации нет, поэтому любой, кто доберётся до вашей полки, сможет скачать каждую книгу и переключать профили, и ничего не зашифровано; ключи объектов — это даже слаги из названий, так что списки в хранилище раскрывают названия ваших книг.
Можно запустить на своей машине или обязательно Cloudflare?И так и так: запускайте локально или на VPS как Node-сервер поверх папки с провайдером файловой системы, либо разверните как Cloudflare Worker с хранилищем R2 — код и библиотека одинаковы в обоих случаях.
Данные моей библиотеки где-либо шифруются?Нет. Библиотека хранится в открытом виде без шифрования, хотя провайдер файловой системы позволяет вам самому разместить её на зашифрованном томе.
Зачем нужен OPDS-каталог?Он представляет вашу библиотеку в машиночитаемом формате каталога, чтобы ридеры вроде Kobo или Kindle могли просматривать и скачивать книги напрямую, без браузера.
Что будет, если читать под одним профилем с двух устройств одновременно?Синхронизация позиции чтения работает по принципу «последняя запись побеждает», поэтому одновременное чтение с двух устройств под одним профилем может перезаписывать прогресс друг друга.
Можно подготовить библиотеку к публичному доступу?Да, установка BOOKSHELFREADONLY в 1 оставляет хранилищу раздачу чтения, но блокирует создание, переименование и удаление профилей, а также сохранение позиций чтения — это рассчитано на полки, до которых могут добраться посторонние.
Есть быстрый способ запустить через Docker?Да, Docker-образ — самый короткий путь: в нём уже есть инструменты для генерации обложек, так что нужно просто смонтировать свои книги и запустить.
Creator
murerkinn
Size
1.3 MB
Stars
372
Updated
CommitAug 25
Age
2mo
Commits · 90 Days