apps/lite/README.md
Electron + React (Vite) + TanStack Router scaffold.
ui/: renderer/frontend codeelectron/: main process and preload codeui imports IPC API types directly from electron/src/ipc.ts using type-only imports for end-to-end type safety.
ui/ and privileged Electron code in electron/.tsc (no extra bundler for main/preload)electron/ TypeScript with tsc only (build:electron).electron-builder via the package script.ui/tsconfig.json, electron/tsconfig.json) plus root project references.moduleResolution: bundler in UI, NodeNext in Electron). Separation prevents subtle config conflicts.electron/src/ipc.ts; preload implements and exposes window.lite; UI consumes types through ambient declaration.contextIsolation: true, nodeIntegration: false, and only expose approved API via contextBridge.#electron/*) and type-only imports.pnpm --filter @gitbutler/lite dev: run Vite + Electronpnpm --filter @gitbutler/lite build: build renderer and Electron codepnpm --filter @gitbutler/lite check: TypeScript checks for both targetspnpm --filter @gitbutler/lite bundle-local: build and package with Electron Builder locally
-dev suffix on the version in package.json must be removedbut CLI is not bundled automatically with this script as there's no known case where it needs to be tested. For it to be bundled, you must manually place a but binary in ./resources/bin/but.pnpm --filter @gitbutler/lite bundle-local-nightly: build and package with Electron Builder locally, using production-like settings
bundle-local, but slower to build as it builds with release optimizationsNo app-local ESLint config is added. The monorepo root flat config in eslint.config.js ignores apps/lite/**, and Lite is linted via oxlint instead.
electron/src/ipc.tswindow.liteui/src/electron.d.ts@gitbutler/but-sdk integrationapps/lite consumes Rust bindings via @gitbutler/but-sdk using a strict process boundary:
electron/src/main.ts that call native bindings (for example listProjectsStatelessNapi).electron/src/ipc.ts and carries SDK-generated types such as ProjectForFrontend.contextBridge in electron/src/preload.cts.window.lite.* and never imports or calls native bindings directly.This keeps native module access in privileged code while preserving end-to-end TypeScript safety in the renderer.