- TypeScript 47%
- Svelte 31.6%
- Lua 12.1%
- Rust 8.8%
- CSS 0.3%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| docs | ||
| plugins | ||
| src-tauri | ||
| ui | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| SPEC.md | ||
| TODO.md | ||
kreeader-metadata-manager
A metadata-review app for GCD / Metron maintainers: browse, fix, and add
comic-issue metadata entries across sources, side by side. All data access is
plugin-driven — each source (GCD, Metron, kreeader) is a Lua plugin (run via
wasmoon in the webview) that defines that service's HTTP calls and column
schema. The same UI runs in a plain browser or as a Tauri 2 desktop app; the
desktop shell adds a native HTTP bridge so plugin requests are not subject to
webview CORS. See SPEC.md for the full design.
Prerequisites
- Node.js 20+ and npm — the UI (Vite + Svelte 5 + TypeScript).
- Rust (stable, via rustup) — only needed for the Tauri desktop app.
- Linux desktop builds additionally need the Tauri system deps:
webkit2gtk-4.1,gtk3, and the usual build tools. See Tauri prerequisites.
Install JS deps once in each package:
npm install # repo root: @tauri-apps/cli
npm --prefix ui install
Browser dev (quickest)
npm --prefix ui run dev # or: npm run dev
Open http://localhost:5173. Everything works in the browser, including the Lua plugin runtime.
Tauri desktop app
npm run tauri:dev # dev window against the Vite dev server
npm run tauri:build # release binary (npx tauri build --no-bundle)
tauri:build produces the binary under src-tauri/target/release/. Always
build through the Tauri CLI, never bare cargo build — the CLI enables the
custom-protocol feature and builds the frontend first; a bare cargo build
produces an app with no embedded frontend.
Rust-side unit tests (the plugin_http bridge):
cargo test --manifest-path src-tauri/Cargo.toml
Plugins
Lua plugin sources live in plugins/ (gcd.lua, metron.lua,
kreeader.lua) and are copied into ui/public/plugins/ at build time, then
fetched at runtime — they are not bundled. The runtime accepts additional
plugin source text, but the current UI does not expose add, enable, or disable
controls.
Plugin files are copied wholesale from plugins/ into ui/public/plugins/
by ui/scripts/copy-plugins.mjs, which runs from the predev, prebuild
and pretest hooks — a new .lua file is picked up with no build change.
It does need an entry in plugins/index.json, which is the manifest the app
fetches to know what to load.
A plugin may also declare settings (non-secret values it cannot
hard-code, such as a server URL, read with host.setting(name) and edited
under Settings → Plugin settings) and optional capabilities. The only
optional capability today is the traced-logo group — logo_propose,
logo_trace_save, logo_trace_search, logo_search_results — which
drives the lasso logo tracer in the entry modal. A source whose plugin does
not implement them does not get the feature, rather than getting a button
that fails; see SPEC.md for the shapes and docs/USER-GUIDE.md for what
it does. The server half is merged on kreeader-server master (b2830d8,
kreeader-server#150): /api/comics/{id}/logotrace, /logopropose and
/api/logos/search. Against an older server every call says so — the
server stamps X-Kreeader-Logo-Trace: 1 on every traced-logo response, so
"this build does not have the feature" is never confused with "no such
comic". Traced-logo calls also require the layout_editor scope on whatever
credential you configure.
Tests
npm --prefix ui test # vitest: geometry, plugin runtime, matching, covers
npm --prefix ui run check # svelte-check + tsc
Both must pass before a push, along with npm run build. vite build does
not typecheck modules nothing imports yet, so check is not optional.
Plugin HTTP: browser vs. desktop
- Tauri app: plugin HTTP goes through the native
plugin_httpcommand (reqwest in the Rust shell), so requests are not subject to webview CORS. - Browser mode: plugin HTTP uses plain
fetch, so it is subject to CORS. For sources that don't send permissive CORS headers, run the app behind a dev proxy (e.g. a Viteserver.proxyentry or any reverse proxy that forwards to the source API) — CORS setup is the deployer's concern.
kreeader-server specifically
The manager cannot fix this from the client side, so it is written down
here rather than discovered. kreeader-server routes every endpoint through
its CORS middleware, which emits Access-Control-Allow-Origin and answers
preflight OPTIONS — but only for the origin named in its own config:
[server]
cors_origin = "http://localhost:5173"
Set it to the origin the manager is actually served from (the Vite dev
server above, or wherever the built app is hosted). With cors_origin
unset — the default — the browser blocks every response before the app
sees it, which surfaces as a send failure with no HTTP status rather than
as an error from the server.
No such setting is needed for the desktop app: its requests go through
the Rust plugin_http bridge, which is not a browser.
A cross-origin response exposes only the CORS-safelisted headers to
JavaScript, so a browser can only read X-Kreeader-Logo-Trace at all
because kreeader-server's CORS middleware lists it in
Access-Control-Expose-Headers (ff5e335 and later). If a genuine 404 reads as
"this server has no
traced-logo endpoints" against a server you believe is current, that
means one of: an old server (before ff5e335), a proxy stripping the header,
or cors_origin not naming this app's origin — not a limitation of a
current server. The desktop build reads every header regardless and is
unaffected by any of this.