Skip to content

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

FilePurpose
src-tauri/tauri.conf.jsonMain Tauri config: product name, version, window size, bundle targets, updater endpoint + pubkey
src-tauri/src/main.rs / src-tauri/src/lib.rsRust entry point and app setup (tray, plugins, commands like set_minimize_to_tray)
src/features/settings/lib/updater.tsFrontend side of auto-update — see Settings & Updates
src/features/settings/lib/globalHotkey.tsRegisters 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 with package.json-style semver (currently 0.1.2)
  • Frontend source: ../dist (the Vite production build) — beforeBuildCommand runs npm run build automatically
  • Bundle target: nsis only (Windows installer) — createUpdaterArtifacts: true so 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.tsx uses HashRouter specifically because the desktop build loads from a file:// 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 signed latest.json matching the pubkey in tauri.conf.json for update checks to succeed.
  • Local dev vs desktop dev: npm run dev runs 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.ts and UpdatesPage.tsx.
  • Cutting an actual signed release -> Release.