Comic Lettering & Localization Workspace Plan, prepare, letter, translate, review and publish comics in multiple languages.
See the code
A workspace for comic lettering, localization and production.
Plan, prepare, letter, translate, review and publish comics in one integrated workflow — on a single machine, over LAN, or with a shared server.
Join the Discord · Download for Windows/macOS/Linux
ComiKumi brings the whole production workflow around your artwork into one place — from script planning to lettering, localization, review, and publishing — without replacing the art itself. Place and letter speech bubbles, curved titles/SFX, and image patches directly on top of scanned comic pages, translate them per language, and export the result as ready-to-publish PNGs. Run it solo on your machine, on your studio's LAN, or on a shared server your whole team connects to — a small Express server reads/writes files on disk (no cloud, no telemetry, no third-party signup), paired with a React + Konva canvas editor. You still create your own ComiKumi account on first launch (see Getting started below) — that account lives on your own server, not a central ComiKumi service.
{漢字|かんじ} or per-character {東|とう}{京|きょう}, the
latter word-protected across column breaks), bōten emphasis dots ({最悪*}, the
traditional alternative to bold/italic), automatic tate-chū-yoko for digit/Latin
runs (fullwidth-normalized, so IME-typed "21" is recognized too), and kinsoku
shori line-breaking rules (see screenshot). Two toolbar buttons insert the furigana/bōten markup for you, with
furigana pre-filled from the glossary when available. See docs/Japanese-Typesetting.md..clip project
files directly as new pages, no manual flattening/export step in CSP first (no
official .clip SDK exists — parsed independently, see
docs/clip-parser-provenance.md). Composites the
page at full resolution from the file's own layer tiles when every visible layer is a
plain raster/paper layer in a known, verified pixel format, falling back to CSP's own
embedded flattened-canvas preview (capped at roughly half the real canvas's
resolution, but always complete) for anything else.docs/FEATURES.md.docs/FEATURES.md. Images can also be pasted
directly from the OS clipboard (e.g. "Copy image" on an AI-generated picture in
ChatGPT's or Gemini's web UI) with Ctrl+V/Cmd+V — into the selected panel's Cut-Panel
replacement, or as a new placed image, no upload dialog required.docs/ocr-model-provenance.md for the
open-weight models used and their licenses.docs/inpainting-model-provenance.md for
the model used and its license.User guide (task-oriented, "how do I…"): docs/User-Guide.md
(also available in German).
Full feature list: docs/FEATURES.md (also available
in German). Layout JSON schema:
docs/JSON-Format.md (also available
in German). Script-planning JSON schema:
docs/Script-JSON-Format.md (also available
in German).
client/ React 19 + Konva 10 (react-konva) editor, Vite + Vitest
server/ Express 5 API — reads/writes project files, images, and layout JSON on disk
shared/ Zod schemas shared by both (layout, project, presets, characters, …)
docs/ Feature docs, JSON format reference, brand assets
No database — a project is a single projekt.json file (name, languages, characters,
glossary, presets, settings) plus your existing folder of scanned pages. The server keeps
its own state in server/data/ (or the app-data directory you chose for a desktop
install) — most of it (fonts/images/SVG library, page thumbnails, a pointer to the
last-opened project) is a regenerable cache, but this directory also holds account
records and the server's own authentication/encryption secrets, so don't delete or
reset it as a cache-clearing step. Pointing the app at a different data directory (e.g.
via the desktop setup screen) does not migrate anything from the old one — it starts a
fresh, empty set of accounts, exactly as if the old directory had never existed.
Most users don't need Node.js, a terminal, or a build step at all — just a desktop download and an installer/AppImage. Building from source (below) is only needed for development, or to run the server on a platform without a prebuilt desktop package.
Preview builds for Windows, macOS (Apple Silicon), and Linux are attached to the ComiKumi 0.9.0 Preview release — scroll to Assets and download the file for your platform. GitHub's own "Source code (zip)"/"Source code (tar.gz)" links on that page are not installers — they're the raw repository source, only useful if you're building from source (below).
| Platform | Download |
|---|---|
| Windows | ComiKumi.Setup.0.9.0.exe |
| macOS (Apple Silicon only — no Intel build yet) | ComiKumi-0.9.0-arm64.dmg |
| Linux | ComiKumi-0.9.0.AppImage |
This is still a preview release — see the release page's own notes for known limitations before relying on it for real production work.
Windows: run ComiKumi.Setup.0.9.0.exe and follow the installer.
macOS: open the .dmg and drag ComiKumi into Applications.
Linux: make the AppImage executable, then run it:
chmod +x ComiKumi-0.9.0.AppImage
./ComiKumi-0.9.0.AppImage
On first launch, a setup screen offers a choice: run a local server (asks where to
store app data — not the comic projects themselves, which are configured per-project
via the in-app Project Wizard in step 5 — and which local port to use, defaulting to
the OS's per-user app-data directory and port 3001), or connect to a remote
ComiKumi server someone else is already running (just its URL — the desktop app then
starts nothing locally, it's a thin wrapper around that server's own web UI).
Revisitable anytime via Datei → Server wechseln…. See
electron/README.md for how packaging, setup, and dev mode work.
The very first time a local server starts with no accounts yet, it shows a one-time setup screen instead of a login — pick a username and password. This first account automatically becomes system administrator and can create further accounts later. Connecting to an existing remote server instead just shows that server's normal login.
Open the in-app Project Wizard and point it at a folder of scanned pages — see
docs/FEATURES.md for the expected folder
convention (a <book>_empty source-page folder per volume, <book>_<language> folders
for translated exports).
Requires Node.js ^20.19.0 || >=22.12.0 (this only matters if you're running from
source or building your own desktop package — end users of the downloads above don't
need Node.js at all).
npm install
npm run dev
This installs both client/ and server/ (via postinstall) and starts them together
(server on :3001, client on :5173, proxied through Vite). Open the printed client
URL and continue from step 3 above.
To build your own desktop package instead of downloading one: npm run electron:build
(or the platform-specific electron:build:win/:mac/:linux variants) packages
ComiKumi as a self-contained desktop app (Electron embeds the same Express server and
serves the built client from one process) — release/<platform> gets the same
installer types listed in step 1.
By default the client talks to http://localhost:3001 when unconfigured (matching the
dev setup above), or same-origin ("", relative paths) in a production build. To point a
built client at a server hosted elsewhere — a different machine, network, or port — set
VITE_API_BASE_URL (a Vite build-time env var, e.g. in client/.env.local) to that
server's absolute origin, no trailing slash:
VITE_API_BASE_URL=https://comikumi.example.com
The server already accepts cross-origin requests from anywhere (cors() with no
origin restriction in server/src/app.ts) and every API route is
gated behind account login and per-project roles (viewer/translator/letterer/admin, plus
a server-wide system-admin bypass — see Konten, Rollen & Zugriffsschutz).
The server does all of its file I/O (scan folders, project files, assets, thumbnails) on
its own local disk, so the actual scanned pages must live on (or be reachable from) the
machine the server runs on, not the client's.
The desktop app's "local server" mode (step 3 above) is meant to run in the foreground
on one person's machine — for a server that stays up unattended for a whole team, use
docker-compose.yml instead:
docker compose up -d
This builds the image from Dockerfile.selfhost (a plain,
non-demo build of the same server + client) and starts it as a persistent container,
restarting automatically on failure or host reboot. Two volumes matter:
comikumi-data (named volume, mounted at /data) — the server's own app data:
accounts, its authentication/encryption secrets, the font/SVG/image library, and page
thumbnails. Back this up — see server/data/ further above for
why this isn't just a disposable cache../projects:/projects (bind mount) — put your actual comic projects (scanned pages)
here, or point it at wherever they already live; the in-app Project Wizard (step 5
above) can then browse to a folder under /projects on first run.Open http://<host>:3001 and continue from step 4 above (create the administrator
account). For real team/internet use, put a reverse proxy (nginx, Caddy, Traefik, …) in
front for TLS — this container itself only serves plain HTTP.
To update, pull the new source and rebuild: docker compose up -d --build. The
comikumi-data volume is untouched by a rebuild, so accounts/settings survive.
Prefer to run it without Docker? Build once and start the compiled server directly — same Node.js requirement as running from source:
npm run build
PORT=3001 LETTERING_DATA_DIR=/path/to/data CLIENT_DIST_DIR=client/dist npm --prefix server run start
Keeping that running unattended (across reboots/crashes) is then up to your platform's own process supervisor (systemd, pm2, Windows Task Scheduler, …) — none is bundled here.
| Command | Description |
|---|---|
npm run dev | Start server + client together (hot reload) |
npm run build | Type-check and build both packages for production |
npm run test | Run the full test suite (server + client) |
Each package also has its own scripts (npm --prefix client run <script>, same for
server) — see their respective package.json.
npm run test
Server tests include route-level integration tests (via supertest) that run against
temporary, isolated project/data directories — they never touch your real project data
or the repo's own server/data/. Client tests cover the pure geometry/typesetting/text
logic shared by the live canvas preview and the PNG export.
A small Playwright suite in e2e/ drives a real browser against real server + client
instances, covering the login screen, opening a project, editing a bubble (with a
reload to confirm it actually persisted), and exporting a page to PNG. One-time setup,
then run from the repo root:
npm --prefix e2e install
npx --prefix e2e playwright install chromium
npm run test:e2e
Every run spins up its own server (port 3101) and client (port 4173) against a
throwaway LETTERING_DATA_DIR/scan-root under e2e/tmp-run/ — separate ports and data
from npm run dev, so the suite can run alongside a real dev session without
interfering with it. Not part of npm run test (browser download + runtime are too
heavy for the default test loop).
React 19 · Konva 10 / react-konva · React Router 7 · Zustand · Zod 4 · Vite 8 · Vitest 4 — Express 5 · Sharp · Multer · Archiver · Nodemailer · Zod 4
Free for Open Source, Indies, and Hobbyists.
ComiKumi is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later). You're free to use, study, modify, and share it — including running a modified version as a network service — as long as you make your source changes available under the same license to anyone who interacts with it.
143 commits
TypeScript
97.8%
CSS
1.8%
Comic Lettering & Localization Workspace Plan, prepare, letter, translate, review and publish comics in multiple languages.
See the code
A workspace for comic lettering, localization and production.
Plan, prepare, letter, translate, review and publish comics in one integrated workflow — on a single machine, over LAN, or with a shared server.
Join the Discord · Download for Windows/macOS/Linux
ComiKumi brings the whole production workflow around your artwork into one place — from script planning to lettering, localization, review, and publishing — without replacing the art itself. Place and letter speech bubbles, curved titles/SFX, and image patches directly on top of scanned comic pages, translate them per language, and export the result as ready-to-publish PNGs. Run it solo on your machine, on your studio's LAN, or on a shared server your whole team connects to — a small Express server reads/writes files on disk (no cloud, no telemetry, no third-party signup), paired with a React + Konva canvas editor. You still create your own ComiKumi account on first launch (see Getting started below) — that account lives on your own server, not a central ComiKumi service.
{漢字|かんじ} or per-character {東|とう}{京|きょう}, the
latter word-protected across column breaks), bōten emphasis dots ({最悪*}, the
traditional alternative to bold/italic), automatic tate-chū-yoko for digit/Latin
runs (fullwidth-normalized, so IME-typed "21" is recognized too), and kinsoku
shori line-breaking rules (see screenshot). Two toolbar buttons insert the furigana/bōten markup for you, with
furigana pre-filled from the glossary when available. See docs/Japanese-Typesetting.md..clip project
files directly as new pages, no manual flattening/export step in CSP first (no
official .clip SDK exists — parsed independently, see
docs/clip-parser-provenance.md). Composites the
page at full resolution from the file's own layer tiles when every visible layer is a
plain raster/paper layer in a known, verified pixel format, falling back to CSP's own
embedded flattened-canvas preview (capped at roughly half the real canvas's
resolution, but always complete) for anything else.docs/FEATURES.md.docs/FEATURES.md. Images can also be pasted
directly from the OS clipboard (e.g. "Copy image" on an AI-generated picture in
ChatGPT's or Gemini's web UI) with Ctrl+V/Cmd+V — into the selected panel's Cut-Panel
replacement, or as a new placed image, no upload dialog required.docs/ocr-model-provenance.md for the
open-weight models used and their licenses.docs/inpainting-model-provenance.md for
the model used and its license.User guide (task-oriented, "how do I…"): docs/User-Guide.md
(also available in German).
Full feature list: docs/FEATURES.md (also available
in German). Layout JSON schema:
docs/JSON-Format.md (also available
in German). Script-planning JSON schema:
docs/Script-JSON-Format.md (also available
in German).
client/ React 19 + Konva 10 (react-konva) editor, Vite + Vitest
server/ Express 5 API — reads/writes project files, images, and layout JSON on disk
shared/ Zod schemas shared by both (layout, project, presets, characters, …)
docs/ Feature docs, JSON format reference, brand assets
No database — a project is a single projekt.json file (name, languages, characters,
glossary, presets, settings) plus your existing folder of scanned pages. The server keeps
its own state in server/data/ (or the app-data directory you chose for a desktop
install) — most of it (fonts/images/SVG library, page thumbnails, a pointer to the
last-opened project) is a regenerable cache, but this directory also holds account
records and the server's own authentication/encryption secrets, so don't delete or
reset it as a cache-clearing step. Pointing the app at a different data directory (e.g.
via the desktop setup screen) does not migrate anything from the old one — it starts a
fresh, empty set of accounts, exactly as if the old directory had never existed.
Most users don't need Node.js, a terminal, or a build step at all — just a desktop download and an installer/AppImage. Building from source (below) is only needed for development, or to run the server on a platform without a prebuilt desktop package.
Preview builds for Windows, macOS (Apple Silicon), and Linux are attached to the ComiKumi 0.9.0 Preview release — scroll to Assets and download the file for your platform. GitHub's own "Source code (zip)"/"Source code (tar.gz)" links on that page are not installers — they're the raw repository source, only useful if you're building from source (below).
| Platform | Download |
|---|---|
| Windows | ComiKumi.Setup.0.9.0.exe |
| macOS (Apple Silicon only — no Intel build yet) | ComiKumi-0.9.0-arm64.dmg |
| Linux | ComiKumi-0.9.0.AppImage |
This is still a preview release — see the release page's own notes for known limitations before relying on it for real production work.
Windows: run ComiKumi.Setup.0.9.0.exe and follow the installer.
macOS: open the .dmg and drag ComiKumi into Applications.
Linux: make the AppImage executable, then run it:
chmod +x ComiKumi-0.9.0.AppImage
./ComiKumi-0.9.0.AppImage
On first launch, a setup screen offers a choice: run a local server (asks where to
store app data — not the comic projects themselves, which are configured per-project
via the in-app Project Wizard in step 5 — and which local port to use, defaulting to
the OS's per-user app-data directory and port 3001), or connect to a remote
ComiKumi server someone else is already running (just its URL — the desktop app then
starts nothing locally, it's a thin wrapper around that server's own web UI).
Revisitable anytime via Datei → Server wechseln…. See
electron/README.md for how packaging, setup, and dev mode work.
The very first time a local server starts with no accounts yet, it shows a one-time setup screen instead of a login — pick a username and password. This first account automatically becomes system administrator and can create further accounts later. Connecting to an existing remote server instead just shows that server's normal login.
Open the in-app Project Wizard and point it at a folder of scanned pages — see
docs/FEATURES.md for the expected folder
convention (a <book>_empty source-page folder per volume, <book>_<language> folders
for translated exports).
Requires Node.js ^20.19.0 || >=22.12.0 (this only matters if you're running from
source or building your own desktop package — end users of the downloads above don't
need Node.js at all).
npm install
npm run dev
This installs both client/ and server/ (via postinstall) and starts them together
(server on :3001, client on :5173, proxied through Vite). Open the printed client
URL and continue from step 3 above.
To build your own desktop package instead of downloading one: npm run electron:build
(or the platform-specific electron:build:win/:mac/:linux variants) packages
ComiKumi as a self-contained desktop app (Electron embeds the same Express server and
serves the built client from one process) — release/<platform> gets the same
installer types listed in step 1.
By default the client talks to http://localhost:3001 when unconfigured (matching the
dev setup above), or same-origin ("", relative paths) in a production build. To point a
built client at a server hosted elsewhere — a different machine, network, or port — set
VITE_API_BASE_URL (a Vite build-time env var, e.g. in client/.env.local) to that
server's absolute origin, no trailing slash:
VITE_API_BASE_URL=https://comikumi.example.com
The server already accepts cross-origin requests from anywhere (cors() with no
origin restriction in server/src/app.ts) and every API route is
gated behind account login and per-project roles (viewer/translator/letterer/admin, plus
a server-wide system-admin bypass — see Konten, Rollen & Zugriffsschutz).
The server does all of its file I/O (scan folders, project files, assets, thumbnails) on
its own local disk, so the actual scanned pages must live on (or be reachable from) the
machine the server runs on, not the client's.
The desktop app's "local server" mode (step 3 above) is meant to run in the foreground
on one person's machine — for a server that stays up unattended for a whole team, use
docker-compose.yml instead:
docker compose up -d
This builds the image from Dockerfile.selfhost (a plain,
non-demo build of the same server + client) and starts it as a persistent container,
restarting automatically on failure or host reboot. Two volumes matter:
comikumi-data (named volume, mounted at /data) — the server's own app data:
accounts, its authentication/encryption secrets, the font/SVG/image library, and page
thumbnails. Back this up — see server/data/ further above for
why this isn't just a disposable cache../projects:/projects (bind mount) — put your actual comic projects (scanned pages)
here, or point it at wherever they already live; the in-app Project Wizard (step 5
above) can then browse to a folder under /projects on first run.Open http://<host>:3001 and continue from step 4 above (create the administrator
account). For real team/internet use, put a reverse proxy (nginx, Caddy, Traefik, …) in
front for TLS — this container itself only serves plain HTTP.
To update, pull the new source and rebuild: docker compose up -d --build. The
comikumi-data volume is untouched by a rebuild, so accounts/settings survive.
Prefer to run it without Docker? Build once and start the compiled server directly — same Node.js requirement as running from source:
npm run build
PORT=3001 LETTERING_DATA_DIR=/path/to/data CLIENT_DIST_DIR=client/dist npm --prefix server run start
Keeping that running unattended (across reboots/crashes) is then up to your platform's own process supervisor (systemd, pm2, Windows Task Scheduler, …) — none is bundled here.
| Command | Description |
|---|---|
npm run dev | Start server + client together (hot reload) |
npm run build | Type-check and build both packages for production |
npm run test | Run the full test suite (server + client) |
Each package also has its own scripts (npm --prefix client run <script>, same for
server) — see their respective package.json.
npm run test
Server tests include route-level integration tests (via supertest) that run against
temporary, isolated project/data directories — they never touch your real project data
or the repo's own server/data/. Client tests cover the pure geometry/typesetting/text
logic shared by the live canvas preview and the PNG export.
A small Playwright suite in e2e/ drives a real browser against real server + client
instances, covering the login screen, opening a project, editing a bubble (with a
reload to confirm it actually persisted), and exporting a page to PNG. One-time setup,
then run from the repo root:
npm --prefix e2e install
npx --prefix e2e playwright install chromium
npm run test:e2e
Every run spins up its own server (port 3101) and client (port 4173) against a
throwaway LETTERING_DATA_DIR/scan-root under e2e/tmp-run/ — separate ports and data
from npm run dev, so the suite can run alongside a real dev session without
interfering with it. Not part of npm run test (browser download + runtime are too
heavy for the default test loop).
React 19 · Konva 10 / react-konva · React Router 7 · Zustand · Zod 4 · Vite 8 · Vitest 4 — Express 5 · Sharp · Multer · Archiver · Nodemailer · Zod 4
Free for Open Source, Indies, and Hobbyists.
ComiKumi is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later). You're free to use, study, modify, and share it — including running a modified version as a network service — as long as you make your source changes available under the same license to anyone who interacts with it.
143 commits
TypeScript
97.8%
CSS
1.8%