No description
  • Vue 56.5%
  • TypeScript 42.5%
  • CSS 0.9%
Find a file
2026-02-20 19:02:36 +01:00
.github Fix: Correctly choose lang (#41) 2026-01-31 22:41:09 +01:00
.husky Feat: Update deps (#44) 2026-02-10 14:39:17 +01:00
app Feat: Update deps (#44) 2026-02-10 14:39:17 +01:00
docker init 2026-01-12 23:01:44 +01:00
prisma Feat: Dedup enabled chapter (#35) 2026-01-28 00:01:35 +01:00
public Feat: more theming (#37) 2026-01-28 21:27:21 +01:00
server feat: handle 429 rate limits in workers with moveToDelayed (#47) 2026-02-19 17:34:45 +01:00
shared Feat: Dedup enabled chapter (#35) 2026-01-28 00:01:35 +01:00
test Fix: Correctly choose lang (#41) 2026-01-31 22:41:09 +01:00
.coderabbit.yaml feat: init reader (#42) 2026-02-10 13:21:14 +01:00
.dockerignore init 2026-01-12 23:01:44 +01:00
.env.example feat: init reader (#42) 2026-02-10 13:21:14 +01:00
.gitignore fix(nuxt-processor): use custom build until fixed upstream (#4) 2026-01-13 13:55:49 +01:00
.nuxtrc Feat: Update deps (#44) 2026-02-10 14:39:17 +01:00
CLAUDE.md Feat: Dedup enabled chapter (#35) 2026-01-28 00:01:35 +01:00
compose.yml feat: init reader (#42) 2026-02-10 13:21:14 +01:00
Dockerfile release v0.5.0 2026-01-18 20:02:55 +01:00
eslint.config.mjs init 2026-01-12 23:01:44 +01:00
LICENSE chore: add license 2026-01-25 18:38:07 +01:00
nuxt.config.ts feat: handle 429 rate limits in workers with moveToDelayed (#47) 2026-02-19 17:34:45 +01:00
package.json release v0.10.2 2026-02-20 19:02:36 +01:00
pnpm-lock.yaml fix: use impit for HTTP requests to bypass Cloudflare TLS fingerprinting (#45) 2026-02-17 11:38:18 +01:00
prisma.config.ts init 2026-01-12 23:01:44 +01:00
README.md chore: add screenshots 2026-01-25 19:49:08 +01:00
tsconfig.json init 2026-01-12 23:01:44 +01:00
vitest.config.ts fix(weebcentral): some chapter number were incorrectly detected (#7) 2026-01-14 13:39:07 +01:00

Dokusho Backends - Tsundoku

With the latest DMCA thingy in mangadex I needed a way to archive what I am reading without it being a manual chore I have to run manually every day. That being said, this is for personal, and only for personal use. Do not use it to massively scrape every single source you know and massively download data please, we need those aggregator website to exist, same as translation group so consider donating to either or both of them. And more importantly supporting the official release of the manga you read by buying them when they are out in your country or even the japanese version, maybe.

This is a Nuxt 4 app because I wanted to try it out, and also because I hate myself apparently. First time doing serious backend work in Nuxt, so expect some questionable decisions.

PRs welcome - if your code works, manual test is passing and isn't a complete disaster, I'll test and merge it as soon as I humanly can.

Features

  • Multi-source scraping: MangaDex, WeebCentral, Suwayomi for the rest
  • Search with MeiliSearch
  • PostgreSQL for actual data storage
  • S3 storage for covers and chapter pages
  • Background job processing with BullMQ/Redis
  • Dashboard for managing your library, should be plenty of functionality for personal use
  • Auth with better-auth (password, OIDC, API keys)
  • Soft delete with grace period (in case you mess up)

Screenshots

Overview Dashboard

More screenshots
Series Sources
Series Sources
Jobs Attention Center
Jobs Attention Center

Working On

  • Better update scheduling, sometimes job are added again when scheduler is running again. I will pin an issue, do not hesitate to reply if you think you have a solution after reading the code

Planned

  • Test ?
  • Maybe a REST API for third party clients, but you can already use the one in server/api/v1/serie for Mihon like source, I hope
  • Mihon extension
  • More sources, if I ever get around to it, otherwise suwayomi source should work fine for now I think
  • Suwayomi extension management from dashboard
  • IA/ML/Other, at some point I would like to implement image upscaling or even translation since I can say what I want it's just a plan with no date

Image Format

Images are stored as WebP (quality 80) by default. For images exceeding WebP's 16,383px dimension limit (e.g., tall webtoon pages), the system automatically falls back to JPEG (quality 85).

This approach provides:

  • Fast encoding (WebP is much faster than AVIF)
  • Good compression for most images
  • Support for very tall images via JPEG fallback

Running

Development

# Start dependencies (postgres, redis, meilisearch, etc.)
docker compose up -d

# Run the app
pnpm dev                    # Server on http://localhost:3000
pnpm processor:dev          # Background workers (separate terminal)

Production

The image supports three commands: server (default), workers, and migrate.

# compose.prod.yml
services:
    dokusho:
        image: ghcr.io/dokushohq/dokusho-backends:latest
        container_name: dokusho-server
        command: server
        env_file: [.env]
        ports:
            - "3000:3000"
        depends_on:
            dokusho-migrate:
                condition: service_completed_successfully

    dokusho-workers:
        image: ghcr.io/dokushohq/dokusho-backends:latest
        container_name: dokusho-workers
        command: workers
        env_file: [.env]
        depends_on:
            dokusho-migrate:
                condition: service_completed_successfully

    dokusho-migrate:
        image: ghcr.io/dokushohq/dokusho-backends:latest
        container_name: dokusho-migrate
        command: migrate
        env_file: [.env]

Combine with compose.yml for the full stack:

docker compose -f compose.yml -f compose.prod.yml up -d

You'll need to set up your environment variables. Check nuxt.config.ts for what's expected, there is an .env.example file to get you started.

Tech Stack

  • Nuxt 4
  • Prisma (PostgreSQL)
  • BullMQ + Redis
  • S3-compatible storage (MinIO, Cloudflare R2, whatever)
  • better-auth

AI

Yes I used claude code to implement this application. I am a senior backend developer so I did not just let it do its thing while watching YouTube but it did write every part of the dashboard itself as I don't want to write frontend code if I can avoid it. I did test it myself extensively, it does not mean everything is perfect but it is useable on normal sized screen. As for the backend, I wrote the implementation of the weebcentral and mangadex source and all the typing around it, I also made the base of the worker code but claude code was used to add more feature to them. Prisma schema is from me too.

I am sorry if you don't like it, truly. But I am not sorry to say I don't have as much time as I would like to spend a month or two writing a fullstack app AND maintaining it nor do I want to spend every moment of my time when I have other hobbies and a ton of other things to do.

I am more than happy to replace AI written code by human written code, most notably on dashboard, as long as it's improving things and/or implementing feature. Not rewriting code for the sake of it.

As the first useable version is mostly done, I will try to replace some of the AI generated code around the backend part, as I think it's were it's the most valuable use of my time and where the functionnality really resides.