Consolidate MangaCircus app, scraper, and Compose baseline

This commit is contained in:
Maashkinoozhe committed 2026-10-07 23:28:20 +02:00
1 parent cfb2d79103
commit eef4ffa07c
103 files changed
+9316 -172

No files matched your search

+49 -3
View File
@@ -4,7 +4,7 @@ A no-frills, self-hosted manga / comic / webtoon reader.
- **Zero dependencies.** A Node.js server (`server.js`, `library.js`) and plain HTML/CSS/JS pages. No build step, no framework, no database server.
- Reads the manga straight from a folder tree. The same folders stay readable in any normal picture viewer.
- Accounts with per-user reading progress, view settings and "new chapter" notifications.
- Accounts with per-user reading progress, view settings, an opt-in Active Reading Clock, a private Reading Story and "new chapter" notifications.
- Reader with three view modes (**Flow**, **Page**, **Book**), a page zoom that leaves the controls alone, and tap zones for mobile.
## Run it
@@ -19,13 +19,40 @@ Open http://localhost:8080. The first account you create becomes the admin. Try
node tools/make-dummy.js library
```
To run the reader, managed scraper and Sentinel together, use `npm run start:all`. Admins can
then manage the persistent download queue, progress, pauses, retries, and rate limits
under **Settings → Admin → Scraper**. The reader continues working if the scraper is stopped.
**Settings → Admin → Collections & metadata** manages grouped tiles, reading order and relationships;
**Settings → Admin → Service health** shows recovery incidents. See [collections](docs/collections.md)
and [resilience](docs/resilience.md) for the ownership and agent-maintenance contracts.
The current Windows installation uses Docker Compose; its old `MangaCircus Supervisor`
Scheduled Task is disabled. Do not run a native duplicate writer. See
[docs/local-deployment.md](docs/local-deployment.md) for its observed layout, health
checks, restart procedure, and recovery point.
### Docker
```bash
node tools/prepare-compose.js
docker compose config -q
docker compose up -d --build
```
`docker-compose.yml` mounts `./library` read-only at `/library` and keeps accounts/progress in the `mangacircus-data` volume (`/data`).
Stop existing native writers before using their data in containers. `docker-compose.yml`
runs reader, scraper and Sentinel with explicit persistent bind mounts (`library/`,
`data/`), file-backed secrets and only a loopback reader port. No named data volume is
used. See [Compose deployment](docs/compose-deployment.md) for local development, VM
recommendations, cutover, image releases and backup/rollback. The local Docker stack
is verified; VM deployment is still pending.
### Settings workspace
Settings has **User** and **Admin** menu groups. User sections cover Reading,
Reading time & privacy, Notifications and Account. Admin sections cover Scraper,
Server & library, Users & access, Collections & metadata and Service health.
Scraper has local Queue, Automatic updates and Hoster settings tabs. Only admins
see administration; personal settings do not poll scraper services. See
[settings navigation](docs/settings-navigation.md) for routes and verification.
### Settings (environment variables)
@@ -37,6 +64,10 @@ docker compose up -d --build
| `SIGNUP` | `closed` | `open` lets anyone create an account. Otherwise the admin adds users under Settings |
| `SCAN_INTERVAL` | `10` | Minutes between automatic library rescans (`0` = only at start and on "Rescan") |
| `COOKIE_SECURE` | – | `1` marks the login cookie `Secure` (use it when you serve over HTTPS) |
| `SCRAPER_URL` | `http://127.0.0.1:8091` | Private scraper daemon URL |
| `SCRAPER_TOKEN` | empty | Shared daemon token; required when it listens beyond loopback |
| `SCRAPER_TOKEN_FILE` | empty | Alternative secret file (used in Compose) |
| `SENTINEL_URL` | `http://127.0.0.1:8092` | Private observation service URL |
Serve it behind a reverse proxy with HTTPS if it is reachable from the internet. All pages use relative URLs, so a sub-path like `/manga/` works.
@@ -63,12 +94,22 @@ library/
## Documentation
Unnumbered MangaDex pilots/one-shots use stable `special-mangadex-<chapter-uuid>`
chapter keys and human labels, not fabricated numbers. Existing numeric IDs remain
unchanged. In Settings → Admin → Scraper, **Inspect & queue** shows the source edition
before **Confirm download**. “Job finished” refers to its selected scope, not verified
whole-series completeness. See the scraper service and library format contracts below.
| Document | For |
|----------|-----|
| [docs/library-format.md](docs/library-format.md) | The folder format: naming rules, page tags, metadata fields, versions, extras, what survives a rename |
| [docs/import.md](docs/import.md) | How the library is scanned and indexed, caching, change detection and notifications, troubleshooting |
| [docs/architecture.md](docs/architecture.md) | Components, data model, API, security, the reader's layout engine, deployment, design decisions |
| [docs/local-deployment.md](docs/local-deployment.md) | Current local Compose deployment, Tailscale access, persistent state, checks, restart, and recovery |
| [docs/settings-navigation.md](docs/settings-navigation.md) | User/Admin settings sections, scraper tabs, routes and UI checks |
| [docs/reading-insights-concept.md](docs/reading-insights-concept.md) | Active-time presentation, private summaries, deletion/export controls, and the future journal design |
| [docs/scraper-guide.md](docs/scraper-guide.md) | Rule book (agent-readable) for scrapers and other tools that write into the library |
| [scraper/AGENT_RUNBOOK.md](scraper/AGENT_RUNBOOK.md) | Conservative scraper workflow and host-specific procedures for automated agents |
---
@@ -81,7 +122,10 @@ library/
| **Book** | Two facing pages, in reading order (right page first for `rtl`). Covers and double pages stand alone. Pairing restarts after each of them, so one odd page never shifts the whole chapter. If pairs still look wrong, **⇄ Shift** moves the pairs of the current section by one page (remembered per chapter) |
- **Which mode opens:** Settings → *Open chapters in* = a fixed mode or *the mode I used last*. With *Use the fitting mode…* on, content that isn't made for your choice opens in the mode that fits (webtoons always open in Flow). That automatic switch never changes your remembered mode. Only clicking a mode in the reader does.
- **Page zoom:** 100 % means the page fits the screen (in Flow: a normal single page fits the screen; for webtoons, the strip is as wide as the screen but never wider than its own width). Pages may end up larger than the screen, exactly fitting, or smaller. Zoom with Ctrl + mouse wheel, touchpad pinch or two-finger pinch on the pages, or with `+` / `-` / `0`. This zooms only the pages; zooming over the toolbar zooms the whole page as usual. When a page is larger than the screen, drag it with the mouse (hand cursor) or pan with a finger. The zoom is remembered per mode for your account. Click the `100%` button to fit again.
- **Page zoom:** 100 % means the page fits the screen (in Flow: a normal single page fits the screen; for webtoons, the strip is as wide as the screen but never wider than its own width). Pages may end up larger than the screen, exactly fitting, or smaller. The toolbar −/+ buttons and keyboard `-`/`+` move in 5-percentage-point steps from 20 % through 600 %; `0` or the percentage button returns to 100 %. Ctrl + mouse wheel, touchpad pinch and two-finger pinch remain continuous for still finer control. This zooms only the pages; zooming over the toolbar zooms the whole page as usual. When a page is larger than the screen, drag it with the mouse (hand cursor) or pan with a finger. Flow locks horizontal movement while the content fits within the viewport, then enables it automatically when zoom makes the content wider. The zoom is remembered per mode for your account.
- **Flow page gap:** Settings → Reading lets each user keep the normal separator between Flow pages or remove it for continuous webtoon artwork and text that crosses image edges.
- **Active Reading Clock:** opt in under Settings → User → Reading time & privacy. No scrolling-speed limit; a visit counts at 60% viewed-page coverage and saves on exit. Pauses in the background or after 30 seconds without reader activity. Tap the clock for this visit's time, coverage, qualification and loading wait.
- **Your Reading Story:** private active-time summaries appear on the library and manga pages when history exists. Chapter rows show the last timed read (60%-coverage visit), rereads remain visible as lifetime time, and Settings lets each user hide, export, or delete their own history. No leaderboards or speed ranking are used.
- **Tap / click zones:**
- Tapping **beside the pages** always shows or hides the controls.
- On a page, its left and right part turn the page, following the reading direction. For `rtl`, the left part goes forward.
@@ -94,6 +138,8 @@ library/
- **Loading:** the next pages (next 3 in Page mode, next 2 spreads in Book mode) are downloaded and decoded in advance, so page turns don't flash. A page that still isn't there shows a spinner. On phones, "Add to home screen" opens the app without browser bars, and the ⛶ button (where supported) goes fullscreen.
- **Progress** is saved per user and chapter version: the last page, whether the chapter is done, and book-mode shifts. The manga page offers *Continue*. Tap a chapter's status to mark it read/unread.
- **Notifications:** press *Notify me* on a manga. When a rescan finds new chapter numbers, they show up under the bell. Optionally, the server also POSTs a short text to a webhook URL of your choice (e.g. an ntfy.sh or Gotify topic, set in Settings).
- **Finding manga:** the library can search titles, alternative titles, and authors; filter by publication status; combine tags with AND matching; and sort by title, activity, or first release date. Tag links on a manga open the library with that tag selected.
- **Manga overview:** metadata is shown in a structured panel (with the complete raw `manga.json` available for inspection). Chapters are newest-first, with multi-select volume filters; selecting no volume means all volumes.
## Files