Sync reading position from Moon Reader app to Bookhive atproto records
atproto bookhive ereader moonreader
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

human update README

+30 -46
+30 -46
README.md
··· 1 1 # spacebee 2 2 3 - A WebDAV shim that impersonates a cloud sync backend for [Moon+ Reader] and 4 - translates its `.po` position files into ATProto reads/writes on your 5 - [bookhive.buzz] book records. 3 + A WebDAV shim for syncing [Moon+ Reader](https://www.moondownload.com) reading position. Translates 4 + the `.po` position files into ATProto reads/writes on your 5 + [bookhive.buzz](https://bookhive.buzz) book records. 6 6 7 - Point Moon+ Reader at `https://spacebee.yourdomain/` (Basic auth). Open a 8 - book, read for a while, pause the app — your `bookProgress` on your PDS 9 - updates. Flip to `bookhive.buzz` and the progress is already there. Flip 10 - between devices and spacebee hands each one the current state. 7 + ```json 8 + { 9 + "$type": "buzz.bookhive.book", 10 + "bookProgress": { 11 + "percent": 11, 12 + "updatedAt": "2026-04-17T10:01:24.000Z", 13 + "moonReader": { 14 + "file": "The Necromancers House - Buehlman Christopher.epub.po", 15 + "position": "1703297605115*21@0#4826:11.1%", 16 + "syncedAt": "2026-04-17T10:01:24.000Z" 17 + }, 18 + "currentChapter": 22 19 + } 20 + } 21 + ``` 22 + 23 + Also serves a static page showing your reading progress. 24 + 25 + > 🚨 *This is vibecoded, I don't know what I'm doing but it works 👍️* 11 26 12 27 ## How it works 13 28 14 - ``` 15 - MoonReader ─[WebDAV: PROPFIND / GET / PUT]──→ spacebee ──→ ATProto PDS 16 - (buzz.bookhive.book) 29 + ```mermaid 30 + graph LR 31 + MR[Moon+ Reader] -->|"WebDAV: PROPFIND / GET / PUT"| SB[spacebee] 32 + SB -->|"buzz.bookhive.book"| PDS[ATProto PDS] 17 33 ``` 18 34 19 35 - `PROPFIND /Books/.Moon+/Cache/` synthesizes a directory listing from your ··· 25 41 matching bookhive record (or catalog-searches and creates one), and 26 42 updates `bookProgress.{percent,currentChapter,moonReader}` on your PDS. 27 43 28 - Non-position WebDAV paths (`Books/.Moon+/Settings/`, etc.) fall through to a 29 - local-disk scratch area rooted at `$PASSTHROUGH_ROOT`. Those files are not 30 - synced anywhere — they just keep Moon+ Reader happy. 44 + Non-position WebDAV paths (`Books/.Moon+/Settings/`, backups, etc.) fall through to a local-disk scratch area rooted at `$PASSTHROUGH_ROOT`. 31 45 32 46 spacebee also serves a small read-only HTML dashboard at `/` that renders 33 47 your bookhive records (currently-reading, finished, etc.). The dashboard and ··· 42 56 | --- | --- | 43 57 | `BSKY_HANDLE` | The handle spacebee writes records as | 44 58 | `BSKY_APP_PASSWORD` | An [app password] for that handle | 45 - | `PDS` | *Optional.* PDS host (e.g. `bsky.social`). If unset, resolved from the handle at first use via the public bsky appview + PLC directory. | 46 59 | `DAV_USER` / `DAV_PASSWORD` | Basic-auth credentials Moon+ Reader will send | 47 60 | `PASSTHROUGH_ROOT` | Local-disk scratch dir for non-`.po` paths | 61 + | `PDS` | *Optional.* If unset, resolved from the handle. | 48 62 49 63 ## Running locally 50 64 ··· 56 70 57 71 Point a test device at `http://<your-laptop>:8080/` as the WebDAV target. 58 72 59 - ## Deploying 60 - 61 - Single Docker container. Build locally or pull an image you've pushed to a 62 - registry, then: 63 - 64 - ```sh 65 - IMAGE=ghcr.io/you/spacebee:latest docker compose up -d 66 - ``` 67 - 68 - The provided `docker-compose.yml` takes the image tag from the `IMAGE` 69 - environment variable and defaults to `spacebee:latest` (expects a local 70 - build). Put behind a reverse proxy with HTTPS — Moon+ Reader requires TLS 71 - for WebDAV. 72 - 73 - ## CI 74 - 75 - `.forgejo/workflows/ci.yml` runs lint + tests on every push and PR. On 76 - pushes to `main` it will also build and push a Docker image, **but only if 77 - `REGISTRY` is set as a repo/org variable**. To enable image publishing, 78 - configure: 79 - 80 - - Repo/org vars: `REGISTRY` (e.g. `ghcr.io`), `IMAGE_NAME` (e.g. `you/spacebee`) 81 - - Repo/org secrets: `REGISTRY_USER`, `REGISTRY_TOKEN` 82 - 83 - If `REGISTRY` is unset, the build job is skipped and the workflow is 84 - test-only — safe to fork without needing any registry credentials. 85 - 86 73 ## Related 87 74 88 - - [`bookhive.buzz`] — the AT Protocol book tracker whose records spacebee 75 + - [bookhive.buzz](https://bookhive.buzz) — the AT Protocol book tracker whose records spacebee 89 76 reads and writes. 90 - 91 - [Moon+ Reader]: https://www.moondownload.com/ 92 - [bookhive.buzz]: https://bookhive.buzz/ 93 - [app password]: https://bsky.app/settings/app-passwords 77 + - [Moon+ Reader](https://www.moondownload.com/) - Android eReader app