# Electron desktop shell — handoff ## Summary The desktop app wraps the Cinny/Paarrot web UI in Electron: custom title bar, system tray, deep links (`paarrot://`), auto-updates, plugin filesystem access, screen capture for calls, and the local HTTP API server. ## User-facing behavior - Frameless/custom **title bar** with window controls (Windows/Linux) - Minimize to **tray**; close may minimize instead of quit (platform config) - `paarrot://` URL protocol for room links - Auto-update checks (electron-updater) - Plugins read/write under `%APPDATA%\paarrot\` ## Architecture ``` electron/main.js (main process) → BrowserWindow → Vite dev server or built cinny dist → IPC: plugins, screen capture, clipboard, updates → PaarrotAPIServer → Tray + protocol handler paarrot:// preload / contextBridge → window.electron in renderer ``` ## Key files | Path | Role | |------|------| | `electron/main.js` | Main process entry | | `electron/api-server.js` | Local HTTP API | | `electron/preload.js` (if exists) | IPC bridge | | `electron-builder.json5` | Packaging config | | `package.json` (root) | `npm run dev`, build scripts | | `dev-app-update.yml` | Update channel config | | `cinny/src/app/components/title-bar/TitleBar.tsx` | Custom title bar UI | | `build-resources/` | Linux after-install, icons | ## Data model | Store | Tool | Contents | |-------|------|----------| | `electron-store` | main.js | Window bounds, user prefs | | UserData | Electron | plugins, caches | Protocol: `PROTOCOL_SCHEME = 'paarrot'` in main.js ## Dependencies - `electron`, `electron-updater`, `electron-store` - `electron-builder` for CI releases - Vite dev server port **38347**; static server **44548** in dev ## Integration points - **local-api**: started with main window - **Plugins**: filesystem paths under `paarrot` app name - **Voice calls**: `desktopCapturer` for screen share - **Deep links**: pending deep link queue until client ready ## Testing ### Manual 1. `npm run dev` — window loads, title bar draggable. 2. Register `paarrot://` link; opens correct room. 3. Tray icon present; restore from tray. 4. Build installer; auto-update check (staging). 5. Install plugin to AppData path; loader finds it. ### Automated - CI: `.gitea/workflows/build.yml` ## Known issues & gotchas - `isDev` detection: `NODE_ENV` or `!app.isPackaged` - Protocol registration differs Windows vs Linux (`after-install.sh`) - Single instance lock for deep links — see `pendingDeepLink` in main.js - Title bar hit-testing CSS sensitive on Windows 11 ## Future work - macOS menu bar parity - Code signing documentation for Windows - Consolidate magic ports into shared config ## Related docs - [local-api HANDOFF](../local-api/HANDOFF.md) - Root [README.md](../../../../README.md) — build instructions ## Add your extra things here - Dev URLs: `VITE_DEV_SERVER = http://localhost:38347`, `PORT = 44548` - App userData folder name: `paarrot` (matches plugin paths in README)