Appearance
Desktop (Tauri)
What it does
Kairo ships as a Windows desktop app by wrapping the same web build in Tauri — a Rust shell that loads the Vite production build (dist/) into a native window, adds OS integration (tray/minimize, global hotkey, autostart, auto-update), and packages it as an NSIS installer.
Files tied to it
| File | Purpose |
|---|---|
src-tauri/tauri.conf.json | Main Tauri config: product name, version, window size, bundle targets, updater endpoint + pubkey |
src-tauri/src/main.rs / src-tauri/src/lib.rs | Rust entry point and app setup (tray, plugins, commands like set_minimize_to_tray) |
src/features/settings/lib/updater.ts | Frontend side of auto-update — see Settings & Updates |
src/features/settings/lib/globalHotkey.ts | Registers the OS-level "open Kairo" hotkey |
Key facts (from src-tauri/tauri.conf.json)
- Product name: Kairo · identifier:
app.kairo.desktop· version: kept in sync withpackage.json-style semver (currently0.1.2) - Frontend source:
../dist(the Vite production build) —beforeBuildCommandrunsnpm run buildautomatically - Bundle target:
nsisonly (Windows installer) —createUpdaterArtifacts: trueso each build also emits the signed update manifest - Window: 1200x800, resizable,
dragDropEnabled: false - Updater endpoint:
https://github.com/SeiynJie/Kairo/releases/latest/download/latest.json, verified against an embedded minisign public key baked into the config
Plugins used: autostart, global-shortcut, process, updater (see the @tauri-apps/plugin-* entries in package.json).
Key concepts / how it connects
- HashRouter, not BrowserRouter.
src/App.tsxusesHashRouterspecifically because the desktop build loads from afile://path, where path-based routing can't resolve. If you ever see routing break only in the desktop build, this is the first thing to check. isDesktop()(src/features/settings/lib/updater.ts) is the single check used everywhere to branch desktop-only behavior ('__TAURI_INTERNALS__' in window).- Auto-update is two-sided: the frontend (
updater.ts) calls the Tauri updater plugin to check/download/install; the publishing side is the release pipeline (see Release) which must produce a signedlatest.jsonmatching the pubkey intauri.conf.jsonfor update checks to succeed. - Local dev vs desktop dev:
npm run devruns the plain Vite web app;npm run app:dev(tauri dev) launches the same app inside the Tauri shell for testing desktop-only behavior (tray, hotkey, updater).
Where to start editing
- Window size/behavior, bundle targets, updater endpoint ->
src-tauri/tauri.conf.json. - Native OS integration (tray, custom commands invoked from the frontend via
invoke(...)) ->src-tauri/src/lib.rs. - Frontend update-check UX ->
src/features/settings/lib/updater.tsandUpdatesPage.tsx. - Cutting an actual signed release -> Release.