Projects yomikata

yomikata

Live · sign-in required

Manga reader for Android and the browser, with its own backend for my library. One reading position on both devices, offline too.

The yomikata reader with an AI-generated manga page, read right to left: a man in a cap wonders which design to pick, despairs for a moment and then takes all six. Below it the page counter at 91 of 197 and the switches for reading direction and panel mode. Alongside it the catalogue, with made-up covers generated as well, such as “Kater Kommissar”, “Klartext” and “Kapselautomat”.
Period
2025 – present
Role
Solo, concept to operations
Status
Live, behind single sign-on
Code
Private repository

I read manga on my phone when I’m out and on the tablet at home, the same series on both. The volumes sit on my own Grimmory server, and its built-in reader was not much use for that. The other apps I tried next either failed against the server or had no reading position the two devices could share.

yomikata is the reader for it: an Android app and a web interface, both against a backend of their own that in turn talks to the library. On top of that comes what separates a manga reader from a comic reader: reading direction is set per series. A mixed library holds both directions, and the server gives the same answer for every series. Downloaded volumes are fully readable in flight mode and clear themselves away once they have been read. Brightness and warm filter sit in the reader itself, not three levels deep in the settings: at night the system’s lowest brightness is still too bright.

Panel mode is the part I like showing most. On the phone it decides whether reading works at all. A double page with seven panels is a picture puzzle on six inches: zoom, drag, lose the reading direction, which with manga runs from right to left. So the page knows its panels. A double tap switches over. After that every tap moves to the next panel, zoomed in and centred with everything else dimmed, and at the end of the page it carries on to the next by itself. The order comes from the data, already in reading direction; the reader never sorts. The panels are found by Magi, an image model trained specifically on manga. The computing happens on my own machine, in a separate tool that rents graphics cards for the big runs and shuts them down again afterwards.

The app is built for a few people with two devices each, and that is where it stays: one appearance, one file format, no filters, no sorting. Their own accounts, their own access and their own reading positions are carried by the backend underneath, and anyone missing the light appearance reads in the browser. Simple before general is a rule I wrote down for myself.

Stack
KotlinComposeRoomTypeScriptExpressSQLiteReactVitePWAPythonFastAPIPyTorch (Magi v2)RunPod

Decisions

ADR 014

Measure the server instead of trusting its description

The Grimmory instance offers an API, but it does not hold everything that description promises. Storing a reading position, of all things, was not among it, and not for a single book. Had that only come to light during the build, it would have cost the one feature the app exists for. Rather than wait for someone else’s software to be updated, the app is cut to what the server demonstrably does.

ADR 004

The higher page wins

Two devices report different pages for the same book, and one of the two has to give way. The usual rule (the newer one wins) would be the wrong one here. Someone on page 80 on the tablet who opens the book on the phone by accident would have page 1 as the fresher entry. The progress would be gone. So the higher page wins, and only an explicit reset may go below it.

ADR 009

Cached is not downloaded

Pages that have been read stay on disk so that paging back is instant. That looks like a download but is not one. And a cache mistaken for an offline guarantee leads to the worst failure there is: opening a book on the train that was still there yesterday. The two stores are therefore kept apart, cleared apart and shown apart. The offline marker goes only on what was deliberately downloaded.

ADR W14

The computing does not belong on the server

The panels have to come from somewhere, and the obvious place would be the backend: a queue, one job per volume, done. But the server is a small VPS. It would then carry a job system and image processing for a task that comes up exactly once per volume. Instead a local tool does the computing, the Panel Studio, and uploads the finished geometry. The server only checks that it holds up. Also rejected: putting the rectangles into the files themselves. There is no format for it that any of the programs involved reads. And every repack would change the files’ checksums, which the reading position hangs on.

ADR 027

Rent graphics cards instead of tormenting my own

Measuring one page takes three and a half seconds on my own CPU. Eighty new volumes are sixteen hours that way, hours in which the machine does nothing else properly. On a rented card the same page takes just over a tenth of a second, and billing is by the minute. The largest run so far was 16,366 pages on two machines, fourteen minutes, fifty cents. That someone else’s hardware gets a pass to my own library was the real objection. So the rented machines fetch a second, short-lived token that is revoked once the run is done.

This site in a different design

Same content, different look. You start on its home page, and every link stays in the chosen design.

What is this? About this site →