Files
MangaCircus/README.md
MaashkinoozheandClaude Opus 5.5 c760141636 Continue row: a run of more than N chapters in order also marks a reread
A done chapter after the head now counts as left again when it was finished
more than rereadDays before the head (default 7) or before a run of more
than rereadChapters chapters read in order up to the head (default 5).
Both are user settings under Library page; 0 turns a rule off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 11:47:45 +01:00

184 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MangaCircus
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, 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.
- A separate **Greatest of All Time** manga-history dashboard, with five-year periods, per-user wish ratings, community ranking, and local-library badges. Its curated titles do not enter the download queue.
## Run it with Docker
The supported way to run MangaCircus is Docker Compose on a Linux host: one image, a **reader**
service (the web app) and a **scraper** service (the managed download queue). Short version:
```bash
git clone <repository-url> mangacircus && cd mangacircus
mkdir -p library data/scraper data/peering data/peering-usage backup .secrets
openssl rand -hex 32 > .secrets/scraper_token && chmod 600 .secrets/scraper_token
cp .env.example .env # set LIBRARY_PATH etc.; see the guide
sudo chown -R 1000:1000 library data backup
docker compose build
bash deploy/circus.sh up # reader first, then the scraper
```
Open http://127.0.0.1:8080. The first account you create becomes the admin. The full guide covers
configuration, LAN and HTTPS access (a ready Caddy setup is included), adding manga, updates, backups,
peering and troubleshooting: **[docs/deployment.md](docs/deployment.md)**.
## Try it without Docker
Needs Node.js 18 or newer, nothing else:
```bash
node tools/make-dummy.js library # five demo manga
npm run start:all # reader on :8080 and the scraper daemon on 127.0.0.1:8091
```
`npm start` runs the reader alone. Admins manage the persistent download queue, pauses, retries and rate
limits under **Settings → Admin → Scraper**. The reader keeps working when the scraper is stopped.
**Settings → Admin → Collections & metadata** manages grouped tiles, reading order and relationships, and
**Settings → Admin → Service health** shows recovery incidents and backups ([collections](docs/collections.md),
[resilience](docs/resilience.md)). Deployment-controlled reading hours and the optional progress-aware quiz
are described in [reading limiter](docs/reading-limiter.md); they are off unless configured.
See [Greatest of All Time](docs/greatest.md) for that dashboard's catalog and voting.
### 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. Only admins see administration ([settings navigation](docs/settings-navigation.md)).
Reader settings (mode, zoom, page tone, skipping) are kept per sign-in: each device or browser keeps its own once you
change one there, and a new sign-in starts from the one you used last. **Settings → Reading → Reader settings per
session** shows every session's state and turns this off for one shared set ([details](docs/architecture.md#67-reader-settings-per-session)).
### Settings (environment variables)
These configure the reader process. In Docker most are set for you by `docker-compose.yml`; the variables
you put in `.env` are listed in [docs/deployment.md](docs/deployment.md#4-configure-env).
| Variable | Default | Meaning |
|-----------------|-------------|---------|
| `PORT` | `8080` | HTTP port |
| `LIBRARY` | `./library` | Library folder (read-only access is enough) |
| `DATA` | `./data` | Where `db.json` (users, progress, votes, notifications) and disposable library-index caches live |
| `SIGNUP` | `closed` | `open` lets anyone create an account. Otherwise the admin adds users under Settings |
| `SCAN_INTERVAL` | `10` | Minutes between shallow library change checks (`0` disables this timer) |
| `FULL_SCAN_INTERVAL` | `1440` | Minutes between full library reconciliations (`0` disables this timer) |
| `READ_AHEAD` | `1` | Read an opened chapter's pages (then the next chapter's) into the OS cache ahead of the browser; `0` = off ([docs/performance.md](docs/performance.md)) |
| `PERF_TRACE` | `0` | `1` = performance trace from the start; it can also be switched at runtime with the file `DATA/perf/trace.on` ([docs/performance.md](docs/performance.md)) |
| `SCAN_CONCURRENCY` | `8` | Chapter folders and images probed at once by an uncached scan (1–64); higher helps on network storage |
| `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) |
| `BACKUP` | – | Existing folder for built-in backups of `DATA`; unset = off. Compose: set `BACKUP_PATH`. Schedule and retention under Settings → Service health ([backup](docs/backup.md)) |
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.
### Sources and copyright
The scraper can download from MangaDex (on by default; official API) and from WeebCentral and MangaPill.
The last two are unofficial sites that mostly host unlicensed copies, so they are **off by default**. An admin
can switch each one on under **Settings → Admin → Scraper → Hoster settings**. Peering can copy chapters
between servers. You are responsible for only downloading and sharing what you are allowed to copy where you live,
and for respecting each site's terms. The scraper is deliberately slow and stops on access errors; it never
bypasses CAPTCHAs, logins or other access controls ([scraper/AGENT_RUNBOOK.md](scraper/AGENT_RUNBOOK.md)).
---
## Library format
Always three folder levels, **Manga / Book / Chapter**, with plain page images in the chapter folder. Page roles are tags in the file name:
```
library/
Moon Garden/ <- manga folder (its name is the manga's id)
manga.json cover.jpg <- optional
v01 Spring/ <- book (volume / season)
c0001 The Seed/ <- chapter
chapter.json <- recommended
0001_cover.jpg 0002.jpg 0003_double.jpg 0004_rot90.jpg 0005_extra.jpg
c0002 Roots [MangaDex]/ <- same number twice = two versions of one chapter
c0002 Roots [Official]/
c0002.5 Tea Time/ <- in-between chapter
x01 Character Sheets/ <- extra chapter, outside the numbering
x01 Specials/ <- extra book
```
## Documentation
| Document | For |
|----------|-----|
| [docs/deployment.md](docs/deployment.md) | Docker deployment: setup, configuration, HTTPS, operation (`deploy/circus.sh`), updates, backups, troubleshooting |
| [docs/library-format.md](docs/library-format.md) | The folder format: naming rules, page tags, metadata fields, chapter dates, versions, extras, what survives a rename |
| [docs/import.md](docs/import.md) | How the library is scanned and indexed, caching, change detection and notifications |
| [docs/architecture.md](docs/architecture.md) | Components, data model, API, security, the reader's layout engine, design decisions |
| [docs/scraper-service.md](docs/scraper-service.md) | The managed download queue, private API and adapter contract |
| [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, rate limits and stop conditions for automated agents |
| [docs/source-modules.md](docs/source-modules.md) | Adding a new source to the scraper |
| [docs/peering.md](docs/peering.md) | Optional server-to-server sharing over mutual TLS |
| [docs/backup.md](docs/backup.md) | Built-in scheduled backup of `data/`, what it contains, retention and restore |
| [docs/settings-navigation.md](docs/settings-navigation.md) | User/Admin settings sections, scraper tabs and routes |
| [docs/reading-insights-concept.md](docs/reading-insights-concept.md) | Active-time presentation, private summaries, export and deletion |
| [docs/resilience.md](docs/resilience.md) | Supervisors, automatic recovery limits and incidents |
| [AGENTS.md](AGENTS.md) | Working on the code: layout, tests, rules for contributors and coding agents |
Unnumbered MangaDex pilots and one-shots use stable `special-mangadex-<chapter-uuid>` chapter keys and
human labels, not invented numbers. 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.
---
## Reading
| | |
|---|---|
| **Flow** | All pages below each other at the same width. Double pages keep the same height and are twice as wide, but never wider than the screen. Webtoon slices join without gaps |
| **Page** | One page (or one double page) at a time |
| **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. 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.
- **Page tone:** the reader's **Tone** button cycles Original → Inverted → Sepia → Dim → Extra dim in Flow, Page and Book. It changes only the artwork, never the controls or site theme. The choice is saved per user; it can also be selected in Settings → User → Reading.
- **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.
- **Continue where you left off:** the first line of the library content (below the search, filters and tags) is one row of the five manga you read most recently that still have something left after the last chapter you read (same tiles as the grid; they stay in the grid too). Left means an unfinished last chapter, an unread later chapter, or — when you are rereading — a later chapter you finished in an earlier pass: more than *N days* before your current position (default 7), or before a run of more than *M chapters* you have since read in order up to it (default 5). Both are set under Settings → User → Reading → *Library page*; 0 turns a rule off. A manga you have caught up on drops out until a new chapter arrives. It hides while a search is typed, a status filter is set, or the library is sorted by *Recently read*; tags and collection grouping do not affect it. Turn it off under Settings → User → Reading → *Library page*.
- **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.
- In Flow: the bottom part of the screen goes forward, the top part goes back.
- The middle of the page also toggles the controls (useful when a zoomed page fills the screen).
- A horizontal swipe also turns pages on touch screens.
- Keys: arrows, Space / PageDown, `i` = controls, `m` = save a moment, `f` = fullscreen, `?` = all shortcuts (also under Settings → User → Keyboard shortcuts).
- **Moments:** the bookmark button in the top bar (or `m`) saves the page you are on (in Book mode the spread) as a moment. A picture that runs over several pages can take up to four: *+ Previous page* / *+ Next page* add them, stacked in Flow and side by side in Page and Book. Drag over the preview to keep only a region (pages it doesn't touch are left out), and pick exactly one category: Twist, Hot, Awesome, Cute, Funny or Feels, plus an optional note. The button is filled on pages that already have one. Each manga page shows *Your moments* as a strip of crops, sorted by story or by when you saved them; click one to step through them, see the full page, edit, delete or jump into the reader at that page. Moments are private to each user.
- **Controls stay out of the way:** they hide as soon as you turn a page or scroll, and come back only with a tap (middle of the page or beside it) or `i`. Scrolling up never brings them back. The first time they hide, a short hint says so.
- **Controls:** the top bar has a chapter picker with every chapter of the manga, grouped by book, with ✓ for read ones. The bottom bar has the page slider, the mode switch, Shift, zoom, the version picker and previous/next chapter.
- **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
```
server.js HTTP server, accounts, progress, votes, notifications (JSON file storage)
library.js folder scanner + image size reader
public/ the web pages (library, manga, reader, settings, login)
scraper/ download queue daemon, source adapters, publisher
peering/ optional server-to-server sharing
deploy/ Docker operations helper (circus.sh) and HTTPS with Caddy
tools/ demo library generator, maintenance and test tools
```
## License
MIT, see [LICENSE](LICENSE). Manga you read or download with it are not covered by this license and belong to their rights holders.