Find a file
Chmouel Boudjnah d8000293ff
Some checks failed
test / lint-openapi (push) Has been cancelled
build / binary (push) Has been cancelled
build / container (push) Has been cancelled
test / test (push) Has been cancelled
fix: Improve mobile layout and touch handling in reader interface
* Adjusted safe area padding, touch target sizes, and fullscreen behavior across
mobile devices.
* Measured reader bar height dynamically to prevent UI overlaps during
orientation changes.
* Refined pointer and tap gesture tracking to prevent accidental triggers.

Signed-off-by: Chmouel Boudjnah <chmouel@chmouel.com>
2026-10-02 11:55:18 +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 fix: Enable uploads during folder onboarding 2026-10-02 11:25:58 +02:00
internal fix: Improve mobile layout and touch handling in reader interface 2026-10-02 11:55:18 +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 feat: Switch the web reader to streaming publication routes 2026-09-07 13:57:30 +02:00
go.sum feat: Switch the web reader to streaming publication routes 2026-09-07 13:57:30 +02:00
LICENSE Design document for liseur-sync 2026-08-10 13:06:47 +02:00
liseur-sync.example.toml feat: Configure BookOrbit retry timing 2026-09-22 11:59:43 +02:00
Makefile fix: Support macOS host IP detection in development server Makefile 2026-10-02 11:25:29 +02:00
README.md feat: sync reader settings between a reader's devices 2026-09-17 07:54:07 +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

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 — typeface, theme, margins and the like — sync too, as a small map of opaque strings per account, so a second device does not have to be set up from scratch. Unlike positions, these resolve by last-writer-wins on the time the reader made the change.

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.