Home / Developers / Extension & Client Architecture

Extension & Client Architecture

How the Browser Importer and the Mihon extension are built, and the server routes they use.

1. Browser Importer

The importer (extensions/xianscan-importer) is a Manifest V3 extension written in TypeScript and bundled with esbuild. build.js produces two packages:

  • dist/ for Chromium browsers, with a background service worker.
  • dist-firefox/ for Firefox, with a background script and the add-on id importer@xianscan.local.

Page scanner (src/content/scanner.ts) collects images in four passes:

  1. <img> elements, reading lazy-load attributes (data-src, data-original, data-lazy-src, data-url and similar), then srcset, currentSrc and src.
  2. CSS background-image on page containers.
  3. When fewer than 3 images are in the page, image URLs found in embedded JSON state scripts.
  4. For virtual-scrolling readers, a MutationObserver remembers every image URL that appears, and matches them to empty page placeholders.

Downloads go through the background script. If a site refuses, the image is fetched from inside the open tab (with the page's cookies), and as a last resort drawn from the page onto a canvas. The access token is only added by the background script and never exposed to web pages.

bash
cd extensions/xianscan-importer
yarn install
yarn build      # dist/ and dist-firefox/
yarn package    # the .zip and .xpi release files

2. Mihon Extension

The Mihon extension (extensions/xianscan-mihon, package eu.kanade.tachiyomi.extension.all.xianscan) targets extension library 1.6 and Android 6+. It sends the access token in an X-XianScan-Token header, only to the configured server, and shows a readable message on 401.

EndpointPurpose
GET /api/mihon/library?page=N&status=&genre=Books, most recently updated first, 50 per page, archived books excluded
GET /api/mihon/search?q=&page=N&status=&genre=Same list, filtered by title, author or artist
GET /api/mihon/genres{ genres: string[] }
GET /api/mihon/manga/<id>Book details and cover URL
GET /api/mihon/manga/<id>/chaptersChapter list (chapter number is the position in the book)
GET /api/mihon/chapters/<id>/pagesPage image URLs (/api/pages/<id>/file, translated output or the original)
GET /api/covers/<id>/file?w=512Cover image
bash
cd extensions/xianscan-mihon

# Debug APK (JDK 21, Android SDK platform 34, build-tools 34.0.0)
./gradlew :app:assembleDebug

# Release APK. Without signing.properties or the SIGNING_* variables it is signed
# with the debug key, and cannot update over the repository version.
./gradlew :app:assembleRelease

# Check that the APK bundles no Kotlin stdlib or host library (needs dexdump)
bash scripts/verify-apk.sh

Gradle names the APK tachiyomi-all.xianscan-v<version>-<buildType>.apk. Every dependency is compileOnly, because the host app provides Kotlin and all libraries.