The Linux packages only installed a single 1024x1024 hicolor PNG, and Plasma's icon lookup returns nothing for a lone oversized icon — confirmed with kiconfinder6 under Papirus-Dark. Generate 16-1024 px PNGs from the favicon and point electron-builder at the directory so every standard hicolor size is installed.
J621 desktop (Electron)
An Electron shell around the web build. The main process serves the SPA from
the privileged app://j621 scheme — a real origin, so localStorage, OPFS,
Web Workers and WebCodecs all behave exactly like they do in Chrome — and the
SPA keeps its normal first-run flow: on launch it asks where the backend is
(or runs in local mode with no backend at all).
The renderer code is not forked: the shell loads frontend/dist as built by
npm run build in frontend/.
Licensed under the Jake Labs Non-Commercial Software Licence — see
../LICENSE.
Layout
src/main.ts window, app:// protocol handler, menu, external links
src/preload.ts window.j621Desktop bridge
electron-builder.yml deb + pacman + nsis packaging
Development
# terminal 1: the SPA with its /api proxy (needs the backend for library pages)
cd frontend && npm run dev
# terminal 2
cd desktop && npm run dev
npm run dev builds the main process and points the window at
http://localhost:5173 (J621_DEV_SERVER). Without the dev server,
npm start builds both halves and serves the bundled SPA over app://j621.
Builds
npm run dist:linux # release/j621-desktop_0.1.0_amd64.deb + j621-desktop-0.1.0.pkg.tar.zst
npm run dist:win # release/J621 Setup 0.1.0.exe (cross-built with wine; untested)
npm run dist:all
deploy/build_desktop.sh wraps the same commands, installs dependencies on
first run and prints sizes plus SHA-256 sums for release notes. Nothing is
published by it; deploy/push_desktop.sh is the one that feeds auto-updates.
The Arch package can be installed and removed with pacman:
sudo pacman -U release/j621-desktop-*.pkg.tar.zst
sudo pacman -R j621-desktop
It installs to /opt/J621 with a /usr/bin/j621-desktop symlink and a
io.j621.desktop launcher entry (StartupWMClass matches the shell's
desktopName). The Windows installer is a per-user NSIS build, so no admin
rights are needed to install or update it — but it is unsigned, so SmartScreen
will warn, and it has not been smoke-tested on real Windows.
Updates
The app checks only when asked (J621 → Check for updates… in the menu):
Linux packages install through pacman/dpkg, which needs administrator rights,
and the Windows build is unsigned, so nothing installs silently. The check
reads latest-linux.yml / latest.yml from the feed configured in
electron-builder.yml (publish.url, baked into app-update.yml); set
J621_UPDATE_URL to point a build at another feed (the smoke test uses this).
Publishing a release:
- Bump
versionindesktop/package.json— that is what the updater compares. ./deploy/push_desktop.sh --winbuilds deb/pacman/NSIS and copies the artifacts plus both channel files intodeploy/data/desktop/, which the frontend nginx serves read-only at/desktop/.- Existing installs find the new version on their next manual check.
package-type in the app resources tells electron-updater whether to run
pacman -U or dpkg -i (both via pkexec/sudo); the per-user NSIS install
updates without elevation.
Smoke test
npm run smoke builds everything, runs Electron headless through xvfb-run
and checks that the bundled SPA loads over app://j621: the SPA fallback, an
asset fetch, localStorage, OPFS, WebCodecs and the preload bridge. It exits
non-zero on failure. With J621_UPDATE_URL set it also checks that the feed
reports the expected version. Pointing J621_DEV_SERVER at the Vite dev
server checks the development path instead of the bundled one.
Backend CORS
A desktop app is cross-origin to the backend, exactly like the frontend-only Docker deployment. Add the shell's origin to the backend:
CORS_ALLOWED_ORIGINS=app://j621
The setup screen shows this hint (with the actual origin) when the connection test fails. Without a backend, choose "Continue without a backend" — the e621-facing pages work the same as in the browser.