- TypeScript 80.5%
- MDX 8%
- Lua 3.5%
- Rust 3.2%
- Swift 1.3%
- Other 3.3%
|
Some checks failed
Android Production Release / build-android (release) Failing after 30m53s
Notable: upstream merged its own official BookOrbit integration (#5487). Kept the fork's BookOrbit implementation (bookorbit service, form, useBookOrbit hook, provision-file import) since it has fork-specific features; upstream's notes-sync engine files (annotationExchange, notesPass, BookOrbitSyncStore...) land alongside as new shared modules. Both hooks mount in FoliateViewer — fork's useBookOrbit plus upstream's bookOrbitProgressProvider via useKOSync. - Kept .github/workflows deleted (Forgejo migration) - Kept fork README - Kept fork BookOrbitForm/BookOrbitClient/types/constants (ours) - IntegrationsPanel, BooknoteItem: took upstream (supersede fork tweaks) - Submodules foliate-js, tao advanced to upstream pins |
||
|---|---|---|
| .devcontainer | ||
| .forgejo/workflows | ||
| .github | ||
| .husky | ||
| .vscode | ||
| .zed | ||
| apps | ||
| data | ||
| docker | ||
| fastlane | ||
| ops | ||
| packages | ||
| patches | ||
| .dockerignore | ||
| .editorconfig | ||
| .gitignore | ||
| .gitmodules | ||
| biome.json | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CONTRIBUTING.md | ||
| Dockerfile | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| SECURITY.md | ||
| tsconfig.json | ||
Readest for BookOrbit
A fork of Readest (v0.11.18) with native BookOrbit sync built in — reading position, reading sessions/stats, two-way highlights, and book status all flow between Readest and your self-hosted BookOrbit instance, no KOReader required.
Why this fork exists
BookOrbit ships an official KOReader plugin (bookorbit.koplugin, Lua) that syncs progress, reading sessions, highlights and book status. Readest is a Next.js + Tauri ebook reader — it has no Lua runtime, so the KOReader plugin cannot be loaded into it. It does ship a KOSync client, which gets you reading position only against BookOrbit's kosync-compatible endpoints.
This fork ports the BookOrbit plugin's behaviour into Readest's TypeScript codebase, so the full sync feature set works natively in Readest on Android — without needing KOReader installed alongside it.
| Sync feature | Stock Readest + KOSync | This fork |
|---|---|---|
| Reading position (kosync-compatible) | ✅ | ✅ |
| Reading sessions / page-read events (Reading Log) | ❌ | ✅ |
| Two-way highlights & notes | ❌ | ✅ |
| Book status (reading / finished / …) | ❌ | ✅ |
| OPDS catalog browse + download | ✅ (built-in) | ✅ |
Download
Pre-built, signed APK for Android (arm64-v8a):
Readest-BookOrbit-arm64-0.11.18.apk— ~72 MB, self-signed (see Signing)
Builds for other arches / platforms aren't produced here. If you need x86_64 / armv7 / iOS / desktop, build from source (below) — the BookOrbit integration code is platform-agnostic.
Set up sync in the app
- Install the APK (enable "Install unknown apps" for your file manager when prompted).
- Add your BookOrbit OPDS library: Settings → OPDS Catalogs → Add, point it at
https://<your-bookorbit>/opds/{token}(same as you'd do in stock Readest). Browse and download books. - Open Settings → Integrations → BookOrbit and configure:
- Server URL:
https://<your-bookorbit-host> - Username / Password: your BookOrbit web login
- (or tap Import provision and pick the
bookorbit_provision.luayou downloaded from BookOrbit's web settings — it pre-fills server/user/key, you just enter the password)
- Server URL:
- Toggle which of the four sync types you want (all on by default).
Sync is then fully automatic:
- On open → match-check registers the book with BookOrbit, pulls remote position + highlights.
- While reading → reading position auto-pushes ~5s after each page turn (debounced); reading time is recorded locally as page-stat events.
- On close → full snapshot sync uploads progress + reading sessions + highlights + book status to BookOrbit.
How books match
Readest's Book.hash is the partial MD5 of the file — identical to KOReader's book identity — so books downloaded via BookOrbit's OPDS catalog match their library entries on BookOrbit automatically. Highlight identity uses the same md5(datetime|pos0) key as the KOReader plugin, so highlights round-trip across KOReader, Readest and the BookOrbit web reader.
Scope & limitations (v1)
- Reading status syncs (
unread/reading/finished/abandoned). Readest has no native rating field, so ratings are not pushed from Readest. - Two-way highlights: Readest pushes its set and applies remote adds/edits (anchored via XPointer → CFI). Readest will not delete a local highlight based on a server signal (safe default); deletions made in Readest do propagate up.
- Self-signed APK: install updates only from builds signed with the same key as the one in this repo. The signing keystore is not committed; rebuilds you make locally will need an uninstall first (see APK Signing).
Building from source
Prerequisites
- Node 20+ / pnpm 11+ / Rust (stable) / Java 21 (JDK)
- Android SDK (API 36 + Build-Tools 35) and NDK r27b
- ~6 GB free for toolchain + build artifacts
One-time setup
git submodule update --init --recursive
pnpm install --ignore-scripts # sharp fails to build from source; not needed for the APK
# Build the wasm vendors (simplecc, jieba) — only once per checkout
cd packages/simplecc-wasm
make generate-dicts # builds the OpenCC dictionaries simplecc embeds
npm run build:cargo # cargo build --release --target wasm32-unknown-unknown
wasm-bindgen target/wasm32-unknown-unknown/release/simplecc_wasm.wasm \
--out-dir ./pkg/web --target web
mkdir -p dist/web && cp pkg/web/* dist/web/
cd -
cd apps/readest-app && pnpm setup-vendors # stages pdfjs + simplecc + jieba into public/vendor
Environment
export ANDROID_HOME=$HOME/Android/sdk # writable SDK root (needs platform-36, build-tools;35)
export ANDROID_SDK_ROOT=$ANDROID_HOME
export NDK_HOME=$HOME/Android/ndk/android-ndk-r27b
export ANDROID_NDK_HOME=$NDK_HOME
export ANDROID_NDK_ROOT=$NDK_HOME
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
export PATH=$JAVA_HOME/bin:$ANDROID_HOME/platform-tools:$PATH
Build the APK
cd apps/readest-app
pnpm exec tauri android init # one-time; generates gen/android + gradle wrapper
# After init, patch the generated launcher icon (workaround for upstream tauri-cli quirk):
# gen/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
# @color/ic_launcher_background -> @drawable/ic_launcher_background
pnpm exec tauri android build -t aarch64
The unsigned APK lands at:
apps/readest-app/src-tauri/gen/android/app/build/outputs/apk/universal/release/app-universal-release-unsigned.apk
APK signing
Android won't install an unsigned APK. Generate a keystore once and reuse it for every build (so updates install over the existing app without an uninstall):
BT=$ANDROID_HOME/build-tools/35.0.0
keytool -genkeypair -keystore ~/readest-bookorbit.jks -alias readest \
-keyalg RSA -keysize 2048 -validity 10000 \
-storepass readest123 -keypass readest123 \
-dname "CN=Readest BookOrbit, O=Self-signed, C=AU"
$BT/zipalign -p -f 4 app-universal-release-unsigned.apk app-aligned.apk
$BT/apksigner sign --ks ~/readest-bookorbit.jks --ks-pass pass:readest123 \
--key-pass pass:readest123 --out Readest-BookOrbit-arm64.apk app-aligned.apk
$BT/apksigner verify Readest-BookOrbit-arm64.apk
Keep your keystore safe. Anyone with
~/readest-bookorbit.jkscan sign APKs that install as updates over yours.
Where the BookOrbit integration lives
apps/readest-app/src/
├── services/bookorbit/
│ ├── BookOrbitClient.ts # HTTP client (port of bookorbit_api.lua)
│ ├── types.ts # BookOrbit wire formats
│ ├── pageStats.ts # build page-stats payload from Readest's stats DB
│ ├── annotations.ts # two-way highlight mapping
│ ├── bookStates.ts # book status → wire format
│ └── provision.ts # parse bookorbit_provision.lua without a Lua runtime
├── types/settings.ts # BookOrbitSettings type
├── services/constants.ts # DEFAULT_BOOKORBIT_SETTINGS
├── components/settings/integrations/
│ └── BookOrbitForm.tsx # the Integrations → BookOrbit sub-page
├── components/settings/
│ └── IntegrationsPanel.tsx # adds the BookOrbit row
└── app/reader/hooks/
└── useBookOrbit.ts # per-book sync lifecycle (match / pull / push / exchange)
The original BookOrbit KOReader plugin source is kept under ref/bookorbit.koplugin/ for reference while porting.
Compatibility
| Component | Tested with |
|---|---|
| BookOrbit server | v2.2.0 (plugin protocol 1.2.0) |
| Readest upstream | v0.11.18 |
| Android | arm64-v8a, API 26+ |
Credits
- Readest — by Bilingify and contributors, licensed AGPL-3.0. This fork is a derivative and remains AGPL-3.0.
- BookOrbit — self-hostable ebook library + reading-stats platform; its KOReader plugin (
bookorbit.koplugin) was the reference implementation this port was written against.
License
AGPL-3.0 — same as upstream Readest. See LICENSE.