{"id":50988255,"url":"https://github.com/cgillinger/colophon","last_synced_at":"2026-06-19T22:31:15.192Z","repository":{"id":356799862,"uuid":"1226342003","full_name":"cgillinger/colophon","owner":"cgillinger","description":"Self-hosted e-book library \u0026 metadata manager with wireless Kobo sync. Auto-fetches metadata + cover art, AI series detection, in-browser EPUB reader. Flask + Docker. A lightweight Calibre-Web alternative that pairs with Komga \u0026 Kavita.","archived":false,"fork":false,"pushed_at":"2026-06-12T09:00:02.000Z","size":11870,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T10:21:14.749Z","etag":null,"topics":["book-management","calibre","calibre-alternative","docker","ebook","ebook-manager","ebook-metadata","ebooks","epub","epub-reader","ereader","flask","kavita","kobo","kobo-sync","komga","metadata","python","self-hosted","selfhosted"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cgillinger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-01T09:13:44.000Z","updated_at":"2026-06-12T09:00:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cgillinger/colophon","commit_stats":null,"previous_names":["cgillinger/colophon"],"tags_count":45,"template":false,"template_full_name":null,"purl":"pkg:github/cgillinger/colophon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgillinger%2Fcolophon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgillinger%2Fcolophon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgillinger%2Fcolophon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgillinger%2Fcolophon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cgillinger","download_url":"https://codeload.github.com/cgillinger/colophon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cgillinger%2Fcolophon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34550858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["book-management","calibre","calibre-alternative","docker","ebook","ebook-manager","ebook-metadata","ebooks","epub","epub-reader","ereader","flask","kavita","kobo","kobo-sync","komga","metadata","python","self-hosted","selfhosted"],"created_at":"2026-06-19T22:31:11.885Z","updated_at":"2026-06-19T22:31:15.177Z","avatar_url":"https://github.com/cgillinger.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Colophon — self-hosted e-book metadata manager with Kobo wireless sync\n\n[![Python](https://img.shields.io/badge/python-3.12-blue?logo=python\u0026logoColor=white)](https://www.python.org/) [![Flask](https://img.shields.io/badge/flask-3.x-green?logo=flask)](https://flask.palletsprojects.com/) [![Docker](https://img.shields.io/badge/docker-ready-2496ED?logo=docker\u0026logoColor=white)](https://www.docker.com/) [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE) [![Version](https://img.shields.io/badge/version-1.24.2-brightgreen)](https://github.com/cgillinger/colophon/releases) [![Kobo compatible](https://img.shields.io/badge/Kobo-wireless%20sync-FF6E1F?logo=rakuten\u0026logoColor=white)](#setting-up-kobo-sync)\n\n**Colophon — the e-book manager.** A self-hosted web app that turns a messy folder of e-book files into a clean, browsable library and syncs it to a Kobo e-reader over WiFi. (Not the printing/publishing term — this is the software.)\n\nColophon scans a folder of e-book files (EPUB, MOBI, AZW3, KEPUB, PDF, CBZ, CBR), fetches and merges metadata from several sources (Google Books, Hardcover, Open Library, Wikidata, Wikipedia, LIBRIS, Calibre), uses AI to detect series, finds cover art, and lets a Kobo e-reader sync the whole library over WiFi.\n\nThis is a personal project I built for my own library. I've published it in case someone else has the same problem and can use it as a head start. Runs in one Docker container, MIT-licensed, no telemetry. Think of it as a lightweight, metadata-focused alternative to Calibre and Calibre-Web that plays nicely with Komga, Kavita and other servers that read embedded metadata.\n\n---\n\n## Screenshots\n\n\u003e Sample library — the books, covers and authors shown are fictional placeholders.\n\n**Shelf view** — the library as a cover wall, with a \"Reading now\" band that picks up where you left off.\n\n![Shelf view](docs/screenshots/library-shelf.png)\n\n**Table view** — a sortable, filterable metadata table.\n\n![Table view](docs/screenshots/library-table.png)\n\n**Book details** — metadata, reading state, rating, and a one-tap reader.\n\n![Book detail](docs/screenshots/book-detail.png)\n\n**In-browser reader** — read EPUBs in any browser; progress syncs back to your Kobo.\n\n![In-browser reader](docs/screenshots/reader.png)\n\n---\n\n## What it does\n\n- Scans a book folder and builds a catalogue\n- Adds books by drag-and-drop or a file picker — batch upload, no rescan needed; freshly added books wear a \"New\" badge for a while\n- Fetches metadata from seven sources (Google Books, Hardcover, Open Library, Wikidata, Wikipedia, LIBRIS, Calibre) and merges them field by field\n- Detects series with AI (Mistral, OpenAI, DeepSeek, or local Ollama)\n- Finds covers from Open Library, Google Books, Hardcover, Wikidata, DuckDuckGo\n- Writes metadata back into the files so other tools see the same data\n- Keeps authors consistent — one canonical entry per author, spelling variants auto-linked, typos flagged for review, one-click merge/rename that relabels every book, with optional Wikidata verification\n- Groups multiple formats of the same book as one entry\n- Syncs to a Kobo over WiFi — covers, downloads, reading progress\n- Reads EPUBs in the browser, with progress synced to your Kobo\n- UI in English and Swedish\n\n## What it doesn't do\n\n- Render comics page by page (Komga and Kavita do that well)\n- Multi-user accounts\n- OPDS\n- Internet-facing auth (it's a LAN tool; Kobo sync uses path tokens)\n- Backups — it writes to your files, so keep your own\n\n---\n\n## How it compares\n\nIf you've searched for any of these, Colophon is aimed at you:\n\n- **A Calibre / Calibre-Web alternative** when you mainly want clean metadata, covers and a nice library view, without running the full Calibre desktop stack.\n- **Wireless Kobo sync for a self-hosted library** — point a Kobo at your own catalogue instead of the Kobo store, and get covers, downloads and reading-progress sync over WiFi. No cable after setup.\n- **A metadata front-end for Komga or Kavita** — Colophon writes metadata *back into the files*, so the server you already run picks up the same titles, authors, series and covers.\n- **An in-browser EPUB reader** with reading progress that syncs to and from your Kobo.\n\nIt is *not* a comics page-reader, a multi-user server, or an internet-facing app — see [What it doesn't do](#what-it-doesnt-do).\n\n---\n\n## Quick start\n\n```bash\ngit clone https://github.com/cgillinger/colophon.git\ncd colophon\ncp .env.example .env\n# Set at least COLOPHON_SECRET_KEY\ndocker compose up -d\n```\n\nOpen `http://localhost:5000`.\n\n---\n\n## Environment variables\n\nAll variables are read from `.env` (loaded via `env_file` in `docker-compose.yml`).\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `COLOPHON_SECRET_KEY` | Yes | — | Flask session secret |\n| `COLOPHON_LIBRARY_DIR` | No | `/books` | Book folder inside the container |\n| `COLOPHON_DATA_DIR` | No | `/data` | Data folder (database, covers) inside the container |\n| `COLOPHON_LIBRARY_HOST` | No | `./bibliotek` | Host path mounted as the book folder |\n| `COLOPHON_DATA_HOST` | No | `./data` | Host path mounted as the data folder |\n| `COLOPHON_LOG_LEVEL` | No | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |\n| `COLOPHON_PUBLIC_URL` | For Kobo sync | — | URL the Kobo uses to reach Colophon, e.g. `http://192.168.x.x:5000` — include the port |\n| `COLOPHON_GOOGLE_BOOKS_KEY` | No | — | Google Books API key |\n| `COLOPHON_AI_API_URL` | No | Mistral URL | AI chat completions endpoint |\n| `COLOPHON_AI_API_KEY` | No | — | AI provider API key |\n| `COLOPHON_AI_MODEL` | No | `mistral-small-latest` | AI model name |\n| `COLOPHON_UPSTREAM_DIR` | No | — | Upstream library path inside the container (for sync) |\n| `COLOPHON_MAX_UPLOAD_MB` | No | `1024` | Max size per uploaded file (in-app upload) |\n| `COLOPHON_NEW_BADGE_DAYS` | No | `14` | Days a newly added book shows the \"New\" badge |\n\nAll API keys can also be set in the web UI under **Settings → API settings**. UI values take priority over environment variables.\n\n---\n\n## Metadata sources\n\nColophon queries these in a progressive flow and merges the results **field by field** (the best value per field wins, with provenance kept). Each can be toggled in **Settings → API settings**.\n\n| Source | Key required | What it adds |\n|---|---|---|\n| Embedded file | No | Title, author and series already inside the e-book — treated as high-trust |\n| Google Books | Optional key | Title, author, description, ISBN, categories |\n| Hardcover | Optional token | Series, genres, synopsis and rating — strong for popular English titles |\n| Open Library | No | Subjects, synopsis and ISBNs — strong for older or obscure titles |\n| Wikidata | No | Structured series **and position in the series**, genre, author, date |\n| Wikipedia | No | Fast description and a thumbnail cover as a fallback |\n| LIBRIS (KB) | No | Swedish national bibliography — authoritative Swedish title/author/publisher/ISBN |\n| Calibre | No | Deep tier via Calibre's own metadata plugins (Goodreads and others) |\n\n## Cover sources\n\n| Source | Key required | Searches by |\n|---|---|---|\n| Open Library | No | ISBN |\n| Google Books | No | ISBN, title, author |\n| Hardcover | Optional token | ISBN, title, author |\n| Wikidata/Commons | No | ISBN |\n| DuckDuckGo | No | Title, author |\n\n## AI providers\n\n| Provider | URL | Free tier |\n|---|---|---|\n| Mistral (recommended) | `https://api.mistral.ai/v1/chat/completions` | ~1M tokens/month |\n| OpenAI | `https://api.openai.com/v1/chat/completions` | Pay-as-you-go |\n| DeepSeek | `https://api.deepseek.com/v1/chat/completions` | Very cheap |\n| Ollama (local) | `http://localhost:11434/v1/chat/completions` | Free, no key needed |\n\n---\n\n## Managing authors\n\nColophon keeps **one canonical entry per author** so every book by the same\nperson is labelled identically — even when the source files spell the name\ndifferently. The **Authors** page (in the sidebar) is where you curate that\nregistry. Spelling variants are auto-linked to the canonical entry, and\nnear-identical entries are flagged as likely duplicates.\n\nEach entry has a status that controls whether the name is written back into\nyour files:\n\n| Status | Meaning | Written to files? |\n|---|---|---|\n| Tentative | Created automatically from file metadata during a scan or upload | No — DB only |\n| Confirmed | You confirmed the spelling is correct | Yes |\n| Authority-linked | Verified against Wikidata; stores the QID, VIAF and LIBRIS ids | Yes |\n\nWhat you can do from the page:\n\n- **Filter to unconfirmed** and tick the checkboxes to **confirm several at\n  once** — the fastest way to clear out freshly-scanned tentative entries.\n- **Rename** or **merge** an entry — both cascade, relabelling every linked\n  book in one sweep.\n- **Verify** an entry against Wikidata to anchor it with authority ids.\n- For likely-duplicate pairs, merge with one click, or **Ask AI** whether the\n  two names are the same person (advisory only — AI proposes, you decide; needs\n  an AI provider configured, see above).\n\nTentative entries are deliberately never written into files until you confirm\nthem, so an auto-guessed spelling can't quietly rewrite your library.\n\n---\n\n## Adding a language\n\nColophon uses Flask-Babel. A new language is a translation file, no code changes.\n\n1. `pybabel init -i messages.pot -d app/translations -l \u003cLANG_CODE\u003e` (e.g. `de`)\n2. Translate `app/translations/\u003cLANG_CODE\u003e/LC_MESSAGES/messages.po`\n3. `pybabel compile -d app/translations`\n4. Add the code to `SUPPORTED_LANGUAGES` in `app/__init__.py`\n5. `docker compose down \u0026\u0026 docker compose build --no-cache \u0026\u0026 docker compose up -d`\n\nPRs with `.po` files welcome.\n\n---\n\n## Setting up Kobo sync\n\nThis points a Kobo e-reader at Colophon as if it were Kobo's own store: WiFi sync, covers and titles on the device, tap to download. One-time setup; after that the Kobo syncs on its own.\n\nYou'll need: a modern Kobo (Libra, Clara, Sage, Forma, Aura) on the same WiFi as Colophon, a USB cable, and a computer. The Kobo must be signed in to a real Kobo account.\n\n### 1. Set the public URL\n\nAdd this to your `.env`:\n\n```\nCOLOPHON_PUBLIC_URL=http://192.168.x.x:5000\n```\n\nUse the URL you'd type in a browser to reach Colophon from inside your network. Include the port if it's not 80. Restart Colophon (`docker compose restart`).\n\n### 2. Generate a device URL\n\nIn Colophon: click the device icon in the top bar (or Settings → Kobo Sync) → **Add device** → name it → **Generate URL**. Copy the URL — it only shows once. If you lose it, revoke and generate a new one.\n\n### 3. Connect the Kobo over USB\n\nPlug it in. When the Kobo asks **Connect** vs **Continue reading**, pick **Connect**. It appears as a USB drive called **KOBOeReader**.\n\n### 4. Find the config file\n\n```\nKOBOeReader/.kobo/Kobo/Kobo eReader.conf\n```\n\n`.kobo` is hidden by default. Show hidden files:\n\n- **Mac (Finder):** `Cmd + Shift + .`\n- **Windows (Explorer):** View tab → tick \"Hidden items\"\n- **Linux:** `Ctrl + H` in most file managers\n\n### 5. Edit the config file\n\nUse a plain-text editor — not Word, not TextEdit in rich-text mode. Notepad, Notepad++, nano, vim, gedit, Sublime are all fine. On Mac TextEdit, switch to plain text via Format → Make Plain Text.\n\nOpen `Kobo eReader.conf` and find the `[OneStoreServices]` section. Replace these four lines (some may be missing — add them):\n\n```\napi_endpoint=\u003cYOUR-COLOPHON-URL\u003e\nimage_host=http://192.168.x.x:5000\nimage_url_template=\u003cYOUR-COLOPHON-URL\u003e/v1/books/{ImageId}/thumbnail/{Width}/{Height}/false/image.jpg\nimage_url_quality_template=\u003cYOUR-COLOPHON-URL\u003e/v1/books/{ImageId}/thumbnail/{Width}/{Height}/{Quality}/{IsGreyscale}/image.jpg\n```\n\nThe last three lines must include `http://192.168.x.x:5000` with the port — the Kobo strips ports from headers, so it has to be spelled out. No quotes, no extra spaces.\n\nKeep a backup as `Kobo eReader.conf.bak` next to the original.\n\n### 6. Eject and unplug\n\nEject KOBOeReader properly (Finder eject button / right-click → Eject) and wait until the Kobo says it's safe to disconnect.\n\n### 7. Sync on the Kobo\n\n**Settings → Sync now**. The first sync of a large library takes a minute or two. Books appear in **My Books**; tap to download. The first download per book converts EPUB to KEPUB on the fly and takes a couple of seconds. Subsequent reads are instant.\n\n### Troubleshooting\n\n- **Nothing after sync.** Check `docker logs colophon` for requests from the Kobo's IP. No requests = wrong URL in the conf file.\n- **Books load but covers don't.** `image_host` or `image_url_template` is wrong or missing the port. Back to step 5.\n- **\"Sync failed\".** Restart the Kobo (hold power 8s). Double-check `COLOPHON_PUBLIC_URL` matches what the Kobo can reach.\n- **Remove a device.** Settings → Kobo Sync → trash icon.\n- **Undo and use Kobo's store again.** Restore the `.bak`, or set `api_endpoint=https://storeapi.kobo.com` and delete the `image_*` lines.\n\n---\n\n## A note about this project\n\nThis is a hobby project I work on when I have time. Issues and PRs are welcome — I read everything, but responses may be slow, which is a matter of time and not interest. Use at your own risk and keep backups of your e-book files.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgillinger%2Fcolophon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcgillinger%2Fcolophon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcgillinger%2Fcolophon/lists"}