Browses a self-hosted OPDS ebook catalog and keeps verified downloads available offline on desktop and Android.

Role

Rust & Tauri Developer

Timeline
April 2026

Technologies

  • Rust
  • Tauri
  • React
  • TypeScript
  • SQLite
  • OPDS

Tools

  • Tokio
  • Tailwind CSS
  • DaisyUI
  • TanStack Query

Background

My ebooks live on a server at home. Getting one onto my laptop or phone still meant opening a browser, saving a file to a downloads folder, and hoping it arrived intact. I wanted a client that treated my own catalog as a catalog, with a real library state for every book.

Solution

ShelfSync connects to any OPDS server and browses the catalog with cover-forward cards. Downloads stream into a .part file, verify against the checksums the server publishes, and rename into place only once they match, so a dropped connection never leaves a half book behind. The offline library tracks each publication through complete, downloading, failed, unavailable, and superseded states. ShelfSync does not open books. It hands the verified file to a reader, which in my case is Leafline.

Process

Most of the work was assuming the remote catalog is unreliable. OPDS feeds are Atom XML, so I parse them with quick-xml and handle missing entries, awkward pagination, and servers that answer slowly. Downloads needed resumable job state that survives an app restart, which is why the SQLite schema tracks provider-scoped publications, acquisitions, file revisions, and download jobs. A book is never identified by its filename alone. The frontend is React with a virtualized grid and TanStack Query, and there are two themes, paper and lamplight. A Calibre compatibility layer still exists from earlier versions; new work goes through OPDS.

Final Product

Impact

Books now reach my laptop and phone with the metadata they had on the server, without a third-party account. Downloads either verify or fail loudly, which is the part I care about most.

Reflection

This was my introduction to Rust and Tauri: async job management, and bridging a systems backend with a React frontend. The harder design question was what ShelfSync should not do. Keeping reading out of it and letting a dedicated reader own that kept both codebases simpler, and it made the file on disk the only thing the two apps share. Next I would work on reconciling the offline library against the server without ever deleting a file on its own.