Skip to content

Repository files navigation

ReadCommons

A self-hosted web reader that shows a book two ways at once: the readable text, and the scanned page it came from. An audio track plays alongside, highlighting the sentence being read.

Point it at a folder of books, open a browser, read. Nothing leaves your machine, and nothing in your library is modified.

ReadCommons: text view and page view, with the spoken sentence highlighted

Why

A great many books are only readable as scans, or only readable in a language you do not have. Both problems have solutions that work in isolation and fall apart together: a translation loses the diagrams, an OCR pass loses the page, an audiobook loses your place. ReadCommons keeps them in one view, so a book that was practically closed to you becomes one you can actually read.

What it does

  • Two views of one book. Text for reading and translation, the original scan for what the text layer loses: schematics, tables, handwriting, marginalia. Switching views keeps your position.
  • Audio synchronised to the sentence. The spoken sentence is highlighted. Click any sentence to move the audio there.
  • Variable speed without pitch artefacts, and a position that survives a reload or a move to another device.
  • A library with full text search. SQLite FTS5, so search is instant and needs no extra service.

Quick start

You need Docker.

git clone https://github.com/readcommons/readcommons.git
cd readcommons
cp .env.example .env          # point READCOMMONS_LIBRARY_ROOT at your books
docker compose -f docker/compose.yml up

Open http://localhost:8710/app/. That is the reader. http://localhost:8710/ is the presentation page, a plain HTML page describing the project for whoever lands on the address without knowing what it is; set READCOMMONS_PUBLIC_SITE=false and / goes straight to the reader instead.

Your books are mounted read only. Everything ReadCommons derives goes to a separate volume, and the originals are never touched.

Details, other install paths and troubleshooting: docs/INSTALL.md.

Put a password on it before exposing it

Out of the box there is no login, which is the right default for a reader bound to loopback on your own machine. The moment the address is reachable from anywhere else, that default is wrong: the API hands out the full text and the audio of every book in the library, to whoever asks.

One account, two settings. Produce the hash, paste the line it prints into .env, add a user name, restart:

python -m readcommons hash-password     # asks twice, prints the hash line
READCOMMONS_AUTH_USER=you
READCOMMONS_AUTH_PASSWORD_HASH=pbkdf2_sha256$600000$...
READCOMMONS_COOKIE_SECURE=true          # behind TLS

The password itself is never written anywhere: only a PBKDF2 hash is stored, and the session that follows a login is a signed cookie, so restarting the server does not sign you out. Everything under /api/ is then closed, which is everything that can return a book. The presentation page and the interface bundle stay public: they are open source and hold no library data.

How it works

  1. It scans your library and indexes what it finds into SQLite FTS5, without writing anything next to your books.
  2. The text view renders EPUB with foliate-js; the page view renders the original PDF with pdf.js. Both are driven by one position, so they cannot drift apart.
  3. An optional alignment pass matches the audio track to the text and stores sentence timings in the data directory.
  4. The player looks up the current sentence from those timings and highlights it, in both views at once.
  5. FastAPI serves the API, the built interface under /app/ and the presentation page at / from one process, so there is one thing to run and one port to expose.

Running it as a service

systemd user units, a Docker deployment, and the nginx blue-green path if you already run nginx: docs/DEPLOY.md.

Contributing

./scripts/dev.sh starts both servers, ./scripts/check.sh runs exactly what CI runs. See CONTRIBUTING.md.

License

MIT. See LICENSE.

About

Self-hosted reader: your books as translated text or original scanned page, with the audio synchronised sentence by sentence. Click a sentence, the voice goes there.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages