* feat(library): in-place import with cloud sync and symmetric local delete
Adds an `inPlace` option to importBook so a source file inside a
registered external library folder is referenced directly via
`book.filePath` instead of being copied into Books/<hash>/. Sidecars
(cover, config, nav) still live under Books/<hash>/.
ingestService routes through shouldImportInPlace, which marks an
import in-place when the absolute source path lives under any of
`settings.externalLibraryFolders` and is NOT inside a per-root
`Books/` subtree. The Readest data dir (`customRootDir`) is
intentionally excluded — that directory is Readest's home and
should freely hold hash copies; in-place is for user-registered
roots (Duokan, Calibre, Moon+ Reader, an iCloud mirror, …).
Cloud sync treats in-place books as first-class:
- uploadBook reads bytes from (book.filePath, 'None') when set.
The cloud key is unchanged, so a peer downloading the book
lands it under Books/<hash>/ as a normal hash copy.
- useBooksSync strips `book.filePath` before pushing — it is a
device-local path that is meaningless on any other device.
- ingestService no longer skips upload for in-place books;
autoUpload / forceUpload behave like any other book. Only
transient imports opt out.
- deleteBook 'local'/'both' now physically removes the source
file at book.filePath (base 'None'). Local-delete semantics
are symmetric with hash-copy books: the local copy is gone,
the cloud backup remains, a future pull restores under
Books/<hash>/. removeFile errors are swallowed.
New `SystemSettings.externalLibraryFolders?: string[]` (no UI yet;
registration entrypoint lands in a follow-up). Added to
BACKUP_SETTINGS_BLACKLIST alongside `localBooksDir` /
`customRootDir` so device-local paths don't ride cloud backups.
Tests: cloud-service, ingest-service, and backup-settings suites
cover in-place delete, multi-root matching, per-root `Books/`
guard, and the backup-strip.
* feat(library): one-tap "read in place" toggle in folder import
Surface the in-place / copy choice as a single "Read books in place (don't copy)" checkbox in the Import-from-Folder dialog. When the user opts in, the chosen directory is registered in `settings.externalLibraryFolders` and ingestService's `shouldImportInPlace` will route the books straight to importBook with `inPlace: true` — no copy into Books/<hash>/, sync still works, local delete still removes the source file (the symmetry was set up in the previous in-place commit).
User experience:
- First-time users hit the toggle once per library folder. The choice is also persisted to localStorage so subsequent dialog opens default to whatever they picked last.
- Repeat imports from a folder that's already registered as an external library folder force the toggle ON and disable it, with a help line explaining that imports from this folder are always in-place. The check is exact-string (after path normalization) so registering /Users/me/Duokan only locks the toggle for that exact path — picking /Users/me/Downloads after Duokan still shows the toggle in its normal state.
- URL-ingress / drag-drop replays go through `runFolderImport` without the dialog and default `readInPlace: false`. They still benefit from in-place automatically when the dropped path lives under an already-registered root, because that decision is made by `shouldImportInPlace` based on settings, not by the dialog flag.
Mechanics:
- ImportFromFolderResult gains `readInPlace: boolean`. ImportFromFolderDialog gains an `initialReadInPlace` prop (seeded from the new `readest:lastImportFolderReadInPlace` localStorage key) and an `isRegisteredExternalRoot` predicate it uses to render the locked / unlocked toggle.
- runFolderImport calls a new `registerExternalLibraryFolder` helper that appends the chosen directory to `settings.externalLibraryFolders` and persists settings, but only when `result.readInPlace` is true. `isRegisteredExternalRoot` does the inverse lookup the dialog needs. Both helpers normalize paths the same way `shouldImportInPlace` does so the predicate matches the ingest layer.
- The new feature has no effect for users who never flip the toggle: `externalLibraryFolders` stays empty, the path-prefix check in `shouldImportInPlace` returns false for every import, and books continue to be copied into Books/<hash>/ exactly as before.
Self-healing for externally-removed in-place books:
Once the dialog lets users opt their library into in-place mode, the source file becomes a piece of state Readest doesn't control — another app may rewrite it (e.g. Duokan persisting reading progress into the epub), the user may move it in Finder, or an external drive may unmount between sessions. Previously, clicking such a book would navigate into the reader, fail inside loadBookContent's `fs.openFile(book.filePath, 'None')` with a low-level IO error, flash an "Unable to open book" toast, and auto-bounce back to the library — leaving the stale library record in place so the next tap reproduces the same dance.
BookshelfItem.handleBookClick now probes availability before navigating, but only for purely-local in-place books (`book.filePath && !book.uploadedAt && !book.deletedAt`). If `appService.isBookAvailable` returns false — which for in-place books means the recorded `book.filePath` no longer exists at the OS level — we dispatch `delete-books` for that hash and show an info toast explaining the removal, instead of opening the reader.
Scope is intentionally narrow:
- Cloud-synced books still flow through `makeBookAvailable`'s on-demand download path; missing local copies trigger a re-download, not a deletion.
- Hash-copy books (no `filePath` set) are not probed: a missing Books/<hash>/ file under normal use signals a bug or filesystem corruption, not user intent, and silently dropping the record would hide the real problem.
- The dispatched delete-books event reuses the existing Bookshelf deletion path, so sidecar metadata and selection state are cleaned up the same way as a user-initiated delete. For in-place books that path doesn't touch any file outside Books/<hash>/, so the now-missing source location (or whatever the user did with it externally) is left alone — symmetric with 165f15a6.
* fix(library): centralize book content resolution
---------
Co-authored-by: Huang Xin <chrox.huang@gmail.com>
latest tag and production runtime errors; add dev compose file, Codespace support, and semver release tagging (#7) (#4277)
latest tag and production runtime errors; add dev compose file, Codespace support, and semver release tagging (#7) (#4277)
latest tag and production runtime errors; add dev compose file, Codespace support, and semver release tagging (#7) (#4277)
latest tag and production runtime errors; add dev compose file, Codespace support, and semver release tagging (#7) (#4277)
Readest
Readest is an open-source ebook reader designed for immersive and deep reading experiences. Built as a modern rewrite of Foliate, it leverages Next.js 16 and Tauri v2 to deliver a smooth, cross-platform experience across macOS, Windows, Linux, Android, iOS, and the Web.
Features • Planned Features • Screenshots • Downloads • Getting Started • Troubleshooting • Support • License
Features
| Feature | Description | Status |
|---|---|---|
| Multi-Format Support | Support EPUB, MOBI, KF8 (AZW3), FB2, CBZ, TXT, PDF | ✅ |
| Scroll/Page View Modes | Switch between scrolling or paginated reading modes. | ✅ |
| Full-Text Search | Search across the entire book to find relevant sections. | ✅ |
| Annotations and Highlighting | Add highlights, bookmarks, and notes to enhance your reading experience and use instant mode for quicker interactions. | ✅ |
| Dictionary/Wikipedia Lookup | Instantly look up words and terms when reading. | ✅ |
| Parallel Read | Read two books or documents simultaneously in a split-screen view. | ✅ |
| Customize Font and Layout | Adjust font, layout, theme mode, and theme colors for a personalized experience. | ✅ |
| Code Syntax Highlighting | Read software manuals with rich coloring of code examples. | ✅ |
| File Association and Open With | Quickly open files in Readest in your file browser with one-click. | ✅ |
| Library Management | Organize, sort, and manage your entire ebook library. | ✅ |
| OPDS/Calibre Integration | Integrate OPDS/Calibre to access online libraries and catalogs. | ✅ |
| Translate with DeepL and Yandex | From a single sentence to the entire book—translate instantly. | ✅ |
| Text-to-Speech (TTS) Support | Enjoy smooth, multilingual narration—even within a single book. | ✅ |
| Sync across Platforms | Synchronize book files, reading progress, notes, and bookmarks across all supported platforms. | ✅ |
| Sync with Koreader | Synchronize reading progress, notes, and bookmarks with Koreader devices. | ✅ |
| Accessibility | Provides full keyboard navigation and supports for screen readers such as VoiceOver, TalkBack, NVDA, and Orca. | ✅ |
| Visual & Focus Aids | Reading ruler, paragraph-by-paragraph reading mode, and speed reading features. | ✅ |
Planned Features
| Feature | Description | Priority |
|---|---|---|
| AI-Powered Summarization | Generate summaries of books or chapters using AI for quick insights. | 🛠 |
| Advanced Reading Stats | Track reading time, pages read, and more for detailed insights. | 🛠 |
| Audiobook Support | Extend functionality to play and manage audiobooks. | 🔄 |
| Handwriting Annotations | Add support for handwriting annotations using a pen on compatible devices. | 🔄 |
| In-Library Full-Text Search | Search across your entire ebook library to find topics and quotes. | 🔄 |
Stay tuned for continuous improvements and updates! Contributions and suggestions are always welcome—let's build the ultimate reading experience together. 😊
Screenshots
Downloads
Mobile Apps
Platform-Specific Downloads
- macOS / iOS / iPadOS : Search and install Readest on the App Store, also available on TestFlight for beta test (send your Apple ID to readestapp@gmail.com to request access).
- Windows / Linux / Android: Visit and download Readest at https://readest.com or the Releases on GitHub.
- Linux users can also install Readest on Flathub.
- Web: Visit and use Readest for Web at https://web.readest.com.
Requirements
- Node.js and pnpm for Next.js development
- Rust and Cargo for Tauri development
For the best experience to build Readest for yourself, use a recent version of Node.js and Rust. Refer to the Tauri documentation for details on setting up the development environment prerequisites on different platforms.
nvm install v24
nvm use v24
npm install -g pnpm
rustup update
Getting Started
To get started with Readest, follow these steps to clone and build the project.
1. Clone the Repository
git clone https://github.com/readest/readest.git
cd readest
2. Install Dependencies
# might need to rerun this when code is updated
git submodule update --init --recursive
pnpm install
# copy vendors dist libs to public directory
pnpm --filter @readest/readest-app setup-vendors
3. Verify Dependencies Installation
To confirm that all dependencies are correctly installed, run the following command:
pnpm tauri info
This command will display information about the installed Tauri dependencies and configuration on your platform. Note that the output may vary depending on the operating system and environment setup. Please review the output specific to your platform for any potential issues.
For Windows targets, “Build Tools for Visual Studio 2022” (or a higher edition of Visual Studio) and the “Desktop development with C++” workflow must be installed. For Windows ARM64 targets, the “VS 2022 C++ ARM64 build tools” and "C++ Clang Compiler for Windows" components must be installed. And make sure clang can be found in the path by adding C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\Llvm\x64\bin for example in the environment variable Path.
4. Build for Development
# Start development for the Tauri app
pnpm tauri dev
# or start development for the Web app
pnpm dev-web
# preview with OpenNext build for the Web app
pnpm preview
For Android:
# Initialize the Android environment (run once)
rm apps/readest-app/src-tauri/gen/android
pnpm tauri android init
pnpm tauri icon ../../data/icons/readest-book.png
git checkout apps/readest-app/src-tauri/gen/android
pnpm tauri android dev
# or if you want to dev on a real device
pnpm tauri android dev --host
For iOS:
# Set up the iOS environment (run once)
pnpm tauri ios init
pnpm tauri icon ../../data/icons/readest-book.png
pnpm tauri ios dev
# or if you want to dev on a real device
pnpm tauri ios dev --host
5. Build for Production
pnpm tauri build
pnpm tauri android build
pnpm tauri ios build
Please refer to our release script if you experience any issues: https://github.com/readest/readest/blob/main/.github/workflows/release.yml
6. Setup dev environment with Nix
If you have Nix installed, you can leverage flake to enter a development shell with all the necessary dependencies:
nix develop ./ops # enter a dev shell for the web app
nix develop ./ops#ios # enter a dev shell for the ios app
nix develop ./ops#android # enter a dev shell for the android app
7. More information
Please check the wiki of this project for more information on development.
Troubleshooting
1. Readest Won’t Launch on Windows (Missing Edge WebView2 Runtime)
Symptom
- When you double-click readest.exe, nothing happens. No window appears, and Task Manager does not show the process.
- This can affect both the standard installer and the portable version.
Cause
- Microsoft Edge WebView2 Runtime is either missing, outdated, or improperly installed on your system. Readest depends on WebView2 to render the interface on Windows.
How to Fix
- Check if WebView2 is installed
- Open “Add or Remove Programs” (a.k.a. Apps & features) on Windows. Look for “Microsoft Edge WebView2 Runtime.”
- Install or Update WebView2
- Download the WebView2 Runtime directly from Microsoft: link.
- If you prefer an offline installer, download the offline package and run it as an Administrator.
- Re-run Readest
- After installing/updating WebView2, launch readest.exe again.
- If you still encounter problems, reboot your PC and try again.
Additional Tips
- If reinstalling once doesn’t work, uninstall Edge WebView2 completely, then reinstall it with Administrator privileges.
- Verify your Windows installation has the latest updates from Microsoft.
Still Stuck?
- See Issue readest/readest#358 for further details, or head over to our Discord server and open a support discussion with detailed logs of your environment and the steps you’ve taken.
2. AppImage Launches but Only Shows a Taskbar Icon
On some Arch Linux systems—especially those using Wayland—the Readest AppImage may briefly show an icon in the taskbar and then exit without opening a window.
You might see logs such as:
Could not create default EGL display: EGL_BAD_PARAMETER. Aborting...
This behavior is usually caused by compatibility issues between the bundled AppImage libraries and the system’s EGL / Wayland environment.
Workaround 1: Launch with LD_PRELOAD (recommended)
You can preload the system Wayland client library before launching the AppImage:
LD_PRELOAD=/usr/lib/libwayland-client.so /path/to/Readest.AppImage
This workaround has been confirmed to resolve the issue on affected systems.
Workaround 2: Use the Flatpak Version
If you prefer a more reliable out-of-the-box experience on Arch Linux, consider using the Flatpak build on Flathub instead. The Flatpak runtime helps avoid system library mismatches and tends to behave more consistently across different Wayland and X11 setups.
Contributors
Readest is open-source, and contributions are welcome! Feel free to open issues, suggest features, or submit pull requests. Please review our contributing guidelines before you start. We also welcome you to join our Discord community for either support or contributing guidance.
Support
If Readest has been useful to you, consider supporting its development. You can become a sponsor on GitHub, donate via Stripe, or donate with crypto. Your contribution helps us squash bugs faster, improve performance, and keep building great features.
Sponsors
License
Readest is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the LICENSE file for details.
The following libraries and frameworks are used in this software:
- foliate-js, which is MIT licensed.
- zip.js, which is licensed under the BSD-3-Clause license.
- fflate, which is MIT licensed.
- PDF.js, which is licensed under Apache License 2.0.
- daisyUI, which is MIT licensed.
- marked, which is MIT licensed.
- next.js, which is MIT licensed.
- react-icons, which has various open-source licenses.
- react, which is MIT licensed.
- tauri, which is MIT licensed.
The following fonts are utilized in this software, either bundled within the application or provided through web fonts:
Bitter, Fira Code, Inter, Literata, Merriweather, Noto Sans, Roboto, LXGW WenKai, MiSans, Source Han, WenQuanYi Micro Hei
We would also like to thank the Web Chinese Fonts Plan for offering open-source tools that enable the use of Chinese fonts on the web.





