desktop
Ship the same app to Windows, macOS and Linux, choosing a small Tauri or a familiar Electron shell.
The desktop platform wraps your app/ in a native window for Windows, macOS and Linux. Pick the shell: Tauri (a small Rust binary around the system webview) or Electron (a bundled Chromium, with electron-vite).
import { desktop } from 'kitr/desktop'
export default defineKitrConfig({
platforms: {
site: web({ mode: 'spa' }),
app: desktop({ shell: 'tauri', title: 'Acme', width: 1200, height: 800 }),
},
})
Install
kitr add desktop app --shell tauriFirst time? Run npm i -g kitr once. Inside a project, the global kitr runs your project's own version.
This installs @kitr/desktop and the shell's tooling, adds the router, platform and storage packages if missing, writes platforms.app into kitrrc.ts, registers the shell's drivers through kitr/desktop/provider, and scaffolds the native project under platforms/app/: src-tauri/ for Tauri, or main.ts, preload.ts and ipc.ts for Electron.
Run it
kitr dev app
kitr build appFirst time? Run npm i -g kitr once. Inside a project, the global kitr runs your project's own version.
kitr dev app starts the Vite dev server and opens the window on it. kitr build app builds the web bundle into dist/app/client, then runs tauri build or electron-vite build and electron-builder for installers. kitr doctor checks the Rust toolchain for Tauri.
Options
| Option | Default | Description |
|---|---|---|
shell |
tauri |
tauri or electron |
port |
3200 |
Dev server port the window loads from |
title, width, height, minWidth, minHeight |
The main window | |
appId |
Bundle identifier (reverse DNS) | |
devtools |
true |
Open devtools in development |
Calling native code
Tauri: declare your Rust commands once and call them typed.
import { commandQuery, defineCommands } from 'kitr/desktop/tauri'
type Commands = { greet: (args: { name: string }) => string }
export const commands = defineCommands<Commands>()
export const greeting = commandQuery(commands.greet, 'greet')
Electron: one IPC schema shared by main, preload and the renderer (platforms/app/ipc.ts), handleIpc() in main, exposeIpc() in preload, and createIpcClient<Ipc>() in the app. Both degrade in a plain browser (ipc.available, isTauri()), so the same app/ ships to the web unchanged.