ComicHero is a self-hosted reading-order tracker for comics. Build curated reading orders, follow your progress across series and story arcs, and enrich tracked comics with metadata from Metron.
Important
Use ComicHero 1.5.1 or later. Earlier releases can send malformed conditional requests to Metron, which may cause accounts to be incorrectly flagged as duplicates and blocked.
Join the Discord to ask questions, share feedback and reading orders, and follow development.
- Create, edit, reorder, rate, and favorite reading orders with per-entry notes and tags.
- Track comics as unread, read, or skipped with progress calculated per user.
- Browse comics by reading order, series, story arc, and character.
- Mark reading orders, series, arcs, and characters as started or favorite.
- Continue active reading from the dashboard and review statistics and achievements.
- Search and import comics, reading lists, series, arcs, and characters from Metron.
- Run scheduled Metron discovery jobs for new comics and reading lists.
- Fill incomplete comic, character, series, and arc metadata automatically, with optional full comic-list pulls for linked resources.
- Choose single-user or multi-user setup, invite users, or enable open registration.
- Optionally give visitors read-only access to shared ComicHero content.
- Connect external services (readers, collection managers) with scoped, revocable API tokens.
- Run as a single container or standalone binary backed by SQLite.
ComicHero shares comics, reading orders, arcs, series, and characters across the instance, while reading state, favorites, ratings, and progress are associated with individual users.
Metron credentials are optional. Omit the METRON_* variables if you only want to manage data manually. A Metron API token is preferred over username/password, which still works as a fallback.
docker run -d \
--name comichero \
--restart unless-stopped \
-p 8080:8080 \
-v comichero-data:/data \
-e METRON_TOKEN=your-metron-api-token \
ghcr.io/lofter1/comichero:latestOpen http://localhost:8080 and complete the first-run setup. ComicHero asks whether the instance should use single-user or multi-user mode and creates its initial account.
The named volume stores the SQLite database and cached cover images. Images are published for tagged releases, and latest points to the newest release. Pin a version such as ghcr.io/lofter1/comichero:1.5.1 when reproducible deployments matter.
cp .env.example .env
docker compose up -dAdd your Metron credentials to .env before starting if you want imports. The included compose.yaml publishes ComicHero on port 8080 and persists /data in the comichero-data volume.
To build the container from your checkout instead of pulling the published image, uncomment build: . in compose.yaml and run:
docker compose up -d --buildEach release provides standalone Linux and macOS binaries for amd64 and arm64. The web interface is embedded, so Node.js is not required at runtime.
curl -LO https://github.com/Lofter1/ComicHero/releases/latest/download/comichero_<version>_linux_amd64.tar.gz
tar -xzf comichero_<version>_linux_amd64.tar.gz
cd comichero_<version>_linux_amd64
cp .env.example .env
./comicheroReplace linux_amd64 with linux_arm64, darwin_amd64, or darwin_arm64 as appropriate. The binary reads .env from its working directory.
Requirements are Go matching backend/go.mod, Node.js 24 LTS, and npm.
npm --prefix ui install
make build-standalone
./dist/comicheroThis builds the Vue frontend, embeds it in the Go application, and writes a standalone executable to dist/comichero.
ComicHero reads the process environment and .env files in the current or parent directory. Process environment variables take precedence.
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP port used by the server. |
DB_PATH |
./data/comicorder.db |
SQLite database file. Parent directories are created automatically. |
COVER_CACHE_DIR |
./public/covers |
Storage directory for downloaded and optimized cover images. |
ACCESS_LOG_PATH |
./data/access.log |
Append-only JSON Lines HTTP access log. Set it explicitly to an empty value to disable file logging. |
STATIC_DIR |
embedded frontend | Optional directory from which to serve frontend files instead of the embedded build. |
METRON_BASE_URL |
https://metron.cloud/api |
Metron API base URL. |
METRON_TOKEN |
empty | Metron API token. Preferred over username/password when set - Basic Auth still works as a fallback. |
METRON_USERNAME |
empty | Metron username used for search, import, and maintenance jobs (Basic Auth, used only when METRON_TOKEN is unset). |
METRON_PASSWORD |
empty | Metron password (Basic Auth, used only when METRON_TOKEN is unset). |
APP_BASE_URL |
http://localhost:<PORT> |
Public origin used in verification and password-reset links. |
COOKIE_SECURE |
auto-detected | Force session cookies to use or omit Secure with true or false. Otherwise TLS and X-Forwarded-Proto are detected. |
SMTP_HOST |
empty | SMTP server for verification and password-reset emails. Links are logged when SMTP is unset. |
SMTP_PORT |
587 |
SMTP server port. |
SMTP_USERNAME |
empty | Optional SMTP username. |
SMTP_PASSWORD |
empty | Optional SMTP password. |
SMTP_FROM |
SMTP username or noreply@localhost |
Sender address for account email. |
For a public deployment, put ComicHero behind HTTPS, set APP_BASE_URL to its public HTTPS origin, and configure SMTP. Ensure the reverse proxy sends X-Forwarded-Proto: https, or set COOKIE_SECURE=true explicitly.
The first-run wizard offers two modes:
- Single-user creates a personal instance with one account.
- Multi-user enables account administration and per-user reading progress.
Multi-user registration defaults to invite_only, where an administrator generates single-use invitation links. Administrators can instead enable open registration; new users then need to verify their email address before receiving a session. Password-reset links expire after 30 minutes.
Public read-only access can be enabled separately. Because comics, reading orders, and related content are shared across the instance, only enable open registration or public access when that exposure is intentional.
Metron supplies optional comic metadata and cover images. With credentials configured, ComicHero can:
- search for and import individual records;
- import complete Metron series and reading lists in background jobs;
- discover newly modified comics and reading lists on a daily, weekly, or monthly schedule;
- repair configurable missing fields on comics, characters, series, and arcs on one shared schedule;
- optionally pull complete character appearance, series issue, and arc issue lists during maintenance;
- prioritize the order in which maintenance processes comics, characters, series, and arcs;
- apply call limits, minimum request intervals, and cooldowns for incomplete records.
Imports and scans are rate-limited upstream. Use your own Metron account, choose conservative schedules, and review Metron’s terms before enabling automation.
ComicHero can be driven by other software — a reading app, a collection manager, a home-server dashboard — through a small, scoped REST API that sits alongside the main web UI. Access is granted per user through API tokens rather than sharing a login session.
- Sign in and open Account in the ComicHero UI.
- In the API tokens panel, select Create token.
- Give it a name (e.g. the name of the service you're connecting), choose the scopes it needs, and optionally set an expiry date.
- Copy the token immediately. It's shown once, in full, and cannot be retrieved again — if you lose it, revoke it and create a new one.
Send it on every request as a bearer token:
curl http://localhost:8080/api/readingOrders \
-H "Authorization: Bearer ch_pat_..."A token can only reach the specific capabilities it was granted — everything else (account management, deleting content, creating more tokens, the rest of the general API, etc.) is unreachable with a token regardless of scope, even if the underlying account has admin rights.
| Scope | Grants |
|---|---|
readingOrders:search |
List and search reading orders (GET /api/readingOrders) |
readingOrders:read |
View a reading order's details, comics, and progress |
readingOrders:next |
Fetch the next unread comic in a reading order |
readingOrders:start |
Start or stop a reading order |
comics:markRead |
Mark, unmark, or skip a comic as read |
Grant only what an integration actually needs — a read-only tracker, for example, only needs readingOrders:search, readingOrders:read, and readingOrders:next.
All paths are relative to /api and require the Authorization: Bearer <token> header shown above.
| Method | Path | Scope | Description |
|---|---|---|---|
GET |
/readingOrders?q=<query> |
readingOrders:search |
Search/list reading orders |
GET |
/readingOrders/{id} |
readingOrders:read |
Reading order detail (comics, progress) |
GET |
/readingOrders/{id}/next |
readingOrders:next |
Next unread comic in the reading order |
POST |
/readingOrders/{id}/start |
readingOrders:start |
Start reading |
DELETE |
/readingOrders/{id}/start |
readingOrders:start |
Stop reading |
PATCH |
/comic/{id}/read |
comics:markRead |
Mark a comic read, unread, or skipped |
The full request/response schemas are in the interactive API docs at /api/docs (see API and health checks) — every operation above is tagged API Tokens or Reading Orders.
TOKEN="ch_pat_..."
BASE="http://localhost:8080/api"
# 1. Find a reading order
curl -s "$BASE/readingOrders?q=Watchmen" -H "Authorization: Bearer $TOKEN"
# 2. Start it
curl -s -X POST "$BASE/readingOrders/7/start" -H "Authorization: Bearer $TOKEN"
# 3. Ask what to read next
curl -s "$BASE/readingOrders/7/next" -H "Authorization: Bearer $TOKEN"
# => {"readingOrderId":7,"done":false,"comic":{"id":42,"title":"Batman (2011) #6", ...}}
# 4. Mark that comic read once the user finishes it
curl -s -X PATCH "$BASE/comic/42/read" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"read": true}'Revoking a token (from the same Account panel) takes effect immediately — any service using it loses access on its next request.
The database contains comic metadata, reading orders, accounts, reading progress, settings, and job state. Cover images are cached separately. In the standard container deployment, both live under /data in the comichero-data volume.
Back up both the SQLite database and cover directory. For a simple consistent backup, stop ComicHero before copying its data volume. Never commit the database, .env, or cached covers to Git.
Database migrations run automatically when ComicHero starts. Before upgrading, back up /data, then pull the desired image and recreate the container:
docker compose pull
docker compose up -dUse the release notes to check for version-specific instructions.
Install dependencies and run all checks:
npm --prefix ui install
make test
make lintRun the backend and Vite development server together with make dev, or separately:
make dev-backend
make dev-uiThe Vite server runs at http://localhost:5173 and proxies /api and /covers to the Go backend. Additional development guidance is in CONTRIBUTING.md.
With ComicHero running:
- Interactive API documentation:
http://localhost:8080/api/docs - Health endpoint:
http://localhost:8080/healthz
ComicHero writes every HTTP request to ACCESS_LOG_PATH as one JSON object per line. Entries include the timestamp, method, path without its query string, response status, duration, response size, remote address, forwarded address, and user agent. This format can be consumed by log-analysis tools and fail2ban filters. Query strings are omitted to avoid recording invite or password-reset tokens.
The standard container stores the log at /data/access.log alongside other persistent application data. ComicHero appends to the file but does not rotate it; configure the host's log-rotation tooling according to your retention requirements.
- Go, chi, Huma, sqlx, SQLite, and goose
- Vue 3, Vue Router, Vite, and a generated service worker
- Docker, Docker Compose, and standalone release binaries
Questions, feedback, and reading-order discussion are welcome in the ComicHero Discord community. For reproducible bugs and feature requests, open a GitHub issue.
See CONTRIBUTING.md for setup, testing, and pull-request guidelines.
Please follow SECURITY.md when reporting a vulnerability.
ComicHero is available under the MIT License.