Jelu: A Self-Hosted Reading Tracker With a Single-File Database and a Real API
Self hosted read and to-read list book tracker
At a glance
- What is it?
- Jelu is a Kotlin and Vue application for tracking read, reading and to-read books, built around a local database and an HTTP API rather than a hosted service. Its metadata import path depends on Calibre's fetch-ebook-metadata, and that dependency shapes how you deploy it.
- Who is it for?
- Adopt Jelu if you want your reading history in a database file you own, you are willing to run either the Docker image or a Java process, and you accept that ISBN and title lookup goes through Calibre's fetch-ebook-metadata. Skip it if you want a hosted service with a large public catalogue, or if you need a metadata provider that is not Calibre or the documented fallback chain.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem Jelu Targets: Losing a Reading History Every Time a Service Shuts Down
The README states the motivation directly: the author became tired of switching providers every time an online service was shut, and tired of exporting and reimporting data with loss in the process. That is the failure mode Jelu is built against. A reading log is a long-lived artefact. It accumulates years of dates, ratings and notes, and it is exactly the kind of data that suffers when the host disappears. Jelu's answer is to keep everything in a single-file database that can be saved anywhere, and to expose an API so the data can be scripted or moved without a manual export step. The audience is narrow and identifiable: people who already run a server, who have a Goodreads export sitting in a downloads folder, and who would rather point a container at a directory than trust another company with ten years of reading history. Multi-user support, including LDAP login and proxy authentication, means the same instance can serve a household or a small group. That is a deliberate scope choice. Jelu is not trying to be a social network with a public catalogue. It is trying to be one person's or one group's library record, stored on hardware they control.
How Jelu Stores and Serves Your Library
The README describes a Spring fat jar that bundles its dependencies, so a single java -jar command starts the whole backend, and the web UI is then reachable at localhost:11111. The frontend is Vue 3, listed in the repository topics alongside Kotlin, so the application is a backend API plus a browser client rather than a server-rendered site. Data lives in a single-file database. The default location is ${user.home}/.jelu/database/, and the README shows how to move it next to the jar with jelu.database.path: . The Docker Compose example splits storage into four mounts: /config, /database, /files/images and /files/imports. That split matters operationally. Covers and imported files are not inside the database file, so a backup that copies only the database will restore your records without the images. The API is the integration surface. The README says you can script it or connect third-party tools, and the embed feature generates code snippets so a book can be displayed on another site, a blog or a markdown note. Reviews can be written and shared with other users on the same instance, which is a per-instance social feature rather than a federated one. Nothing in the material describes sync between instances, so treat each deployment as its own island.
Metadata Import Runs Through Calibre, and That Is the Main Architectural Constraint
The README is unusually blunt here: automatic metadata online search is provided through a Calibre tool called fetch-ebook-metadata, whether you like it or not. For a Java install, you set jelu.metadata.calibre.path to the executable, for example /usr/bin/fetch-ebook-metadata. The Docker image embeds that executable, which is the strongest practical argument for using the container rather than the jar. If you run the jar on a host without Calibre, the automatic search path is unavailable until you install it and point the config key at it. The README also mentions fallback metadata providers and links to the configuration page of the official documentation for how to set them up, but it does not list them in the README itself. So the import pipeline has two layers: a primary search through fetch-ebook-metadata, and a fallback chain whose details live outside the README. Beyond online search, Jelu can import from a Goodreads CSV export, from a file of ISBNs one per line, and from epub or OPF files. There is also ISBN scanning via camera on mobile. Third-party links to Google Books, Amazon, Goodreads and LibraryThing are either fetched online or computed from provider IDs you enter yourself. That last detail is a useful escape hatch: if the automated lookup returns the wrong edition, you can supply the provider ID and let Jelu build the link.
Getting It Running: Compose File, Config Keys and the CORS Default
The README gives two installation paths. The Java path is to download the jar from the releases section into a folder, run java -jar jelu-0.13.0.jar from that folder, and optionally place an application.yml beside it to override defaults from src/main/resources/application.yml. The Docker path is a Compose file with image wabayang/jelu, container name jelu, port 11111:11111, and the four volume mounts listed above, plus a read-only mount of /etc/timezone. The Compose example sets restart: unless-stopped. One configuration detail deserves attention before you expose the instance. The README states that the default CORS behaviour is to accept everything, and that no config entry is equivalent to jelu.cors.allowed-origins: ['*']. If you run Jelu on a host reachable from the internet, that default is the wrong starting point. The README shows the fix: set jelu.cors.allowed-origins to a list containing your actual origin, such as https://jelu.myserver.org. There is also an unofficial Helm chart linked on ArtifactHub for Kubernetes deployments, which the README labels as unofficial, so treat its values file as community-maintained rather than part of the project's own release surface. The README does not document an authentication bootstrap flow, an admin account creation step, or a reverse proxy configuration, so plan to check the official documentation site for those before putting the instance behind a public hostname.
Where Jelu Is the Wrong Tool
The dependency on fetch-ebook-metadata is the clearest limitation. On a minimal host, a container that lacks the binary, or a platform where Calibre is awkward to install, the automatic import feature degrades to manual entry, ISBN lists, or epub and OPF files. That is not a bug, but it changes the daily experience significantly: adding a book becomes a data-entry task rather than a search. Second, the README does not describe a mobile application. ISBN scanning via camera is listed as a feature, which implies a mobile browser experience, but there is no native client mentioned. If your reading workflow depends on an app with offline sync, Jelu's browser UI is a different proposition. Third, the project is single-instance by design. Reviews are visible to other users on your instance, and there is no mention of federation, shared catalogues or cross-instance discovery. Someone looking for a social reading network will not find one here. Fourth, the release cadence visible in the material is fast: v0.84.6, v0.85.0 and v0.86.0 appear within roughly two weeks of each other, and the version is still in the 0.x range. Fast 0.x releases usually mean schema changes and migration steps arrive with them. The README does not describe a migration or backup procedure, so anyone running this in production should read the release notes for each upgrade rather than pulling latest blindly.
Alternatives and the Actual Difference in Approach
The README itself names the comparison it cares about: Jelu acts as a self-hosted personal Goodreads. The difference is structural. Goodreads is a hosted service with a shared catalogue and social graph; Jelu is a local database with an API and a browser UI, and its social features stop at the users of your own instance. If what you want is discovery and other people's reviews, Jelu is the wrong shape entirely. Calibre's own content server is the other obvious point of comparison, and the relationship is unusual: Jelu depends on a Calibre tool for metadata lookup but is not a Calibre frontend. Calibre is built around managing ebook files, converting formats and reading them; Jelu is built around tracking what you read, with covers and imports as supporting data. If your library is a folder of epubs that you actually read in Calibre, Jelu is a second system to maintain. If your library is a list of titles and dates, Jelu is closer to the point. The README mentions LibraryThing and Goodreads as link targets and import sources, which reinforces that Jelu positions itself as the record of reading rather than the store of books. That distinction should drive the decision more than any feature checklist.
Maintenance, Licence and What to Verify Before You Commit
Jelu is MIT licensed, which is permissive and places few obligations on how you run or modify it. That is a statement about the licence text, not legal advice; if you plan to redistribute a modified build, read the licence yourself. The maintenance cost is mostly operational. You are running a JVM process or a container, backing up a database file plus the images and imports directories, and tracking 0.x releases that arrive frequently. The Docker image bundles fetch-ebook-metadata, which removes one moving part, but it also means the image is larger than a bare JVM and that metadata behaviour is tied to the Calibre version inside the image. The Java path trades image size for a manual Calibre install and a config key. Either way, the upgrade path is the part the README does not cover, and it is the part that matters most once you have data you care about. Verify three things before you migrate a real library into it: that your backup copies all four mounted directories, not just the database file; that jelu.cors.allowed-origins is set to your origin rather than left at the permissive default; and that automatic metadata search returns sane results for a handful of your ISBNs before you import a few thousand rows.
Editorial conclusion
Adopt Jelu if you want your reading history in a database file you own, you are willing to run either the Docker image or a Java process, and you accept that ISBN and title lookup goes through Calibre's fetch-ebook-metadata. Skip it if you want a hosted service with a large public catalogue, or if you need a metadata provider that is not Calibre or the documented fallback chain. Before committing, run the Docker Compose file from the README, confirm that /files/images and /files/imports are writable, and check whether your instance needs jelu.metadata.calibre.path set or the image's bundled binary is enough.
Community notes