Find a file
Chmouel Boudjnah 37e61a9c9f
Some checks failed
build / binary (push) Has been cancelled
build / container (push) Has been cancelled
test / test (push) Has been cancelled
test / lint-openapi (push) Has been cancelled
docs: Fix the sittings descriptions in the API spec
2026-10-18 15:34:46 +02:00
.github chore: configure Copilot Go environment 2026-09-09 04:22:04 +02:00
cmd/liseur-sync feat: Add admin UI section to configure reading position mirroring 2026-09-22 10:11:48 +02:00
docs docs: Fix the sittings descriptions in the API spec 2026-10-18 15:34:46 +02:00
internal fix: Count reading sittings instead of every pause 2026-10-18 15:24:44 +02:00
scripts docs: photograph the reader in the theme it opens in 2026-09-10 23:21:35 +02:00
tools/reader perf: Keep the next chapter ready so turning into it is instant 2026-09-24 13:54:56 +02:00
.gitignore feat: Switch the web reader to streaming publication routes 2026-09-07 13:57:30 +02:00
.golangci.yml fix: add golangci-lint configuration and pre-commit hooks 2026-08-15 17:56:13 +02:00
.ko.yaml feat: Add web administration panel with account-level roles 2026-08-15 20:22:05 +02:00
.pre-commit-config.yaml fix: redirect after a settings mutation instead of rendering in place 2026-08-22 11:59:49 +02:00
.reflex.conf chore: Add development environment configuration and Makefile 2026-08-15 20:22:01 +02:00
AGENTS.md fix: Allow building the internal content package on macOS 2026-09-13 18:06:16 +02:00
CLAUDE.md feat: Implement initial reading position sync server backend 2026-08-10 16:19:12 +02:00
compose.yaml fix(deploy): name the environment variables the server reads 2026-08-18 22:29:57 +02:00
Dockerfile fix(deploy): name the environment variables the server reads 2026-08-18 22:29:57 +02:00
go.mod chore: Update Go module dependencies 2026-10-17 10:49:43 +02:00
go.sum chore: Update Go module dependencies 2026-10-17 10:49:43 +02:00
LICENSE Design document for liseur-sync 2026-08-10 13:06:47 +02:00
liseur-sync.example.toml feat: keep translated sentences on the account 2026-10-13 07:26:56 +02:00
Makefile fix: Support macOS host IP detection in development server Makefile 2026-10-02 11:25:29 +02:00
README.md feat: keep translated sentences on the account 2026-10-13 07:26:56 +02:00
SECURITY.md fix: harden credential enrolment 2026-08-20 06:10:51 +02:00

liseur-sync

Liseur Sync — an open book encircled by mint and gold sync arrows

Self-hosted server for book libraries and reading-position synchronization.

liseur-sync is the companion server for Liseur. It also provides a kosync-compatible API for KOReader.

The server is a single Go binary with SQLite by default, optional PostgreSQL, and multi-user support.

Library

Insights

Interfaces

liseur-sync provides:

  • reading-position synchronization using full locators
  • a native REST API
  • a kosync-compatible API for KOReader
  • OPDS 1.2
  • EPUB library indexing and search
  • EPUB upload and deletion for writable folders
  • a browser based EPUB reader that supports offline reading.
  • per-user reading statistics and sessions
  • per-user series claims
  • a per-account sentence translation cache.

API documentation is available in docs/openapi.yaml.

Client implementation notes and the synchronization protocol are documented in docs/integrating.md.

Reading synchronization

Reading-position updates are stored as an append-only log rather than replacing the previous position.

This allows the server to resolve updates from multiple devices without an older client blindly replacing newer state. The same history is used to derive reading sessions and statistics.

Book identity is independent of its filesystem path. Clients can resolve books using content and metadata identifiers, including hashes, before exchanging reading state.

Reader preferences synchronize as well per device.

Library

liseur-sync can index either:

  • a directory containing EPUB files
  • a Calibre library using metadata.db

Plain directories derive series information from their directory structure. Calibre libraries use metadata.db as the catalog source.

Catalogs are exposed through the web UI, REST API, and OPDS.

Book details

Folder access

Folders are granted to accounts individually. Adding a folder does not automatically make it visible to every account.

From the CLI:

liseur-sync admin add-folder -assign alice Shelf /srv/books

Folders can also be configured under:

Settings > Administration > Folders

Account folder grants are managed under:

Settings > Administration > Users

Writable folders

Folders are read-only by default.

Uploads and deletions are only allowed for folders explicitly configured to accept uploads:

liseur-sync admin folder-uploads <folder-id> on

For API clients:

  • library-upload permits adding books to writable folders
  • library-delete permits removing books from writable folders

These are separate token scopes.

Deleting through the web UI requires an administrator account.

A folder that does not accept uploads remains read-only: the server indexes its contents but does not add or remove files from it.

See:

Web reader

liseur-sync includes a browser-based EPUB reader.

Reader

The reader uses the same synchronization API as other clients, so reading state is shared with Liseur, KOReader, and other compatible clients.

When another device has read further, the reader offers to continue there, naming both pages, how long ago the other device was there, and the passage it had on screen. The same comparison can be asked for at any time with the sync button in the reader bar (s), which shows both positions and offers to take the other one, keep this page, or cancel and change nothing. The library and the offline shelf refresh on a pull-down, or with their refresh button: pending reading is delivered first, then the page is redrawn. See ADR-0040.

EPUB content is unpacked and rendered without exposing publisher files through normal application routes. Scripts embedded in EPUBs are not executed.

The reader design and security model are documented in ADR-0007, including support for running the reader on a separate hostname.

Offline PWA

Liseur-sync's web UI ships as a PWA that lets you read books offline. From the library, choose Save offline for each book you want to carry, then install the site via your browser's "Add to Home Screen" option (Safari, Chrome, etc.). The installed app opens downloaded books without a network connection and keeps positions, reading sessions, highlights and notes locally until it can reconnect.

Installation

Install script

The installer supports Docker and rootless Podman.

curl -fsSL https://raw.githubusercontent.com/chmouel/liseur-sync/main/scripts/install.sh | bash

Alternatively:

git clone https://github.com/chmouel/liseur-sync.git
cd liseur-sync
scripts/install.sh

To install a specific version:

LISEUR_VERSION=vX.Y.Z scripts/install.sh

The installer configures the database, starts the server, and creates the initial account.

Docker Compose

SQLite:

docker compose --profile sqlite up -d

Bundled PostgreSQL:

docker compose --profile postgres up -d

External PostgreSQL:

docker compose --profile external up -d

Build from source

go build ./cmd/liseur-sync
./liseur-sync serve

Initial setup

The web interface is available at:

/ui/

When the database contains no accounts, the setup page creates the initial administrator account and can watch a first folder of books in the same step.

Users, folders, API tokens, folder grants, and reader pairing can be managed from the administration interface or with the admin CLI.

Deployment details, including TLS, KOReader pairing, Calibre integration, watched folders, and backups, are documented in docs/deployment.md.

Client integration

Liseur uses the native API.

Protocol and synchronization details:

docs/integrating.md

OpenAPI specification:

docs/openapi.yaml

Security

Security issues should be reported according to SECURITY.md.

Do not report security vulnerabilities through public GitHub issues.

License

MIT.

The screenshots use public-domain editions from Standard Ebooks and are generated by scripts/screenshots.sh.