ADR-003: Electron-First Desktop Shell
- Status: Accepted
- Date: 2026-05-17
- Owners: Desktop shell maintainers
- Supersedes (in part): ADR-001 — desktop runtime target selection
Context
ADR-001 established Tauri as the first-party native desktop shell, explicitly rejecting Electron. A
functional Tauri shell was built and validated (packages/desktop, now packages/desktop-tauri).
After shipping the Tauri MVP, the following practical concerns emerged:
- Build and toolchain friction. The Tauri build chain requires Rust, platform-specific system libraries, and a non-trivial CI matrix. Renderer and main-process code cannot share a single TypeScript toolchain—all native IPC commands must be maintained as a matching pair of Rust code and TypeScript bindings.
- Webview rendering divergence. WKWebView (macOS) and WebView2 (Windows) do not share the same
rendering engine as the development browser. CSS, layout, and canvas behaviour diverge silently and
have already required several Tauri-specific workarounds in
packages/workspace. - IPC model. Tauri’s string-serialised Rust IPC adds an extra marshalling layer and makes it harder to share types between the host and the renderer without a separate code-generation step.
- Plugin host trajectory. The community-plugin host direction described in ADR-001 assumes a JavaScript-capable sidecar process. Electron’s Node.js main process makes that sidecar trivially available as a worker/child process; Tauri would require a separate JS runtime binary alongside the Rust shell.
- Ecosystem tooling. The packaging, signing, notarisation, and auto-update ecosystem around Electron is more mature and better integrated with TypeScript monorepos.
The conclusion is that Electron is the better long-term host for a TypeScript-native notes app and is better aligned with the plugin host goals of ADR-001.
Update (2026-05-27): The paused Tauri shell (
packages/desktop-tauri) and alltauri-desktopruntime code have since been removed from the repository. Electron is now the sole first-party desktop host. Legacytauri-foldervault profiles are still accepted and migrated todesktop-folderon open.
Decision
Lapis Notes adopts Electron as the first-party native desktop shell.
1. Runtime targets
The approved product targets are:
web-pwa— browser-hosted and installable web application (unchanged)electron-desktop— first-party native desktop distribution using Electron
2. Package layout
| Package | Purpose | Status |
|---|---|---|
packages/desktop-electron | First-party Electron shell | Active |
Root dev:desktop and desktop:build scripts target @lapis-notes/desktop-electron.
3. Desktop host responsibilities (unchanged)
The host-responsibility split from ADR-001 and the existing desktop spec applies to the Electron shell unchanged:
@lapis-notes/workspaceremains the renderer shell. It owns layout, vault bootstrap, bundled-plugin registration, and sequential boot.@lapis-notes/desktop-electronowns Electron app lifecycle, native window behaviour, IPC command handlers, and desktop-only runtime adapters.@lapis-notes/apiremains the runtime kernel. The desktop host adds adapters, not domain services.
4. Native IPC command surface
The Electron shell exposes this native command surface through the shared API bridge:
desktop_pick_vault_folder— native folder-picker dialogdesktop_fs_*— vault-scoped file operations (exists, stat, read_text, read_binary, write_text, write_binary, list, mkdir, rmdir, remove, copy, rename)desktop_db_load_state/desktop_db_save_state— generated-state persistence outside the vault
Path-safety rules are preserved: .., root, and absolute-subpath escapes are rejected; all operations
are scoped beneath the selected vault root.
5. Desktop-neutral API bridge
The shared native desktop bridge in packages/api uses a runtime-neutral interface
(NativeDesktopBridge, setNativeDesktopBridge, hasNativeDesktopBridge, etc.) implemented by the
Electron shell.
RuntimeTarget includes electron-desktop. VaultStorageKind uses desktop-folder; legacy
tauri-folder profiles are accepted and migrated transparently on open.
6. Community-plugin host trajectory
The plugin host direction from ADR-001 is unchanged in intent. The Electron main process takes the role of the JavaScript-capable sidecar. The concrete design of the Electron community-plugin host boundary is captured in Community Plugin Host Boundary.
7. Packaging and signing
Packaging identifiers, icons, signing/notarisation, auto-update policy, and release-channel metadata for the Electron shell are deferred to a separate task (TASK-DESKTOP-013).
Consequences
- Electron becomes the gating validation target for native desktop work. CI, smoke tests, and first-party documentation describe the Electron shell.
- The workspace renderer uses
electron-desktopas the desktop runtime discriminator anddata-desktop-drag-regionmarkers for frameless window dragging. - Legacy
tauri-foldervault profiles are migrated todesktop-folderon open so existing desktop vault state is preserved.
Alternatives Considered
1. Continue with Tauri and address toolchain friction incrementally
Rejected. The IPC type-safety and sidecar architecture problems are structural, not incidental. Tauri improvements would require ongoing parallel Rust and TypeScript maintenance that is disproportionate to the benefit given the current team size.
2. Target only web-pwa and drop native desktop entirely
Rejected. A native desktop distribution is a first-class product goal. File-system vault access, native menus, OS-level theming integration, and desktop-grade performance under large vaults are not achievable in the browser-only target.
3. Introduce a new desktop framework rather than reverting to Electron
Rejected. Electron’s ecosystem maturity, TypeScript-native main process, and existing Chromium rendering engine alignment with the development browser are decisive advantages. No other framework provides the same combination at this time.
Follow-up
Rename(done).packages/desktoptopackages/desktop-tauriand createpackages/desktop-electronImplement the Electron native IPC command surface(done).Neutralise legacy desktop bridge names to(done).NativeDesktopBridgeand related symbolsAdd Electron desktop validation and smoke coverage(done).- Choose packaging identifiers, icons, signing/notarisation, and updater policy (TASK-DESKTOP-013).
Add native file watching for local-folder vaults(done).- Design the Electron community-plugin host boundary (completed in Community Plugin Host Boundary); implementation proceeds through the Plugin Runtime items documented on the owning contract pages.
Remove the paused Tauri shell and(done, 2026-05-27).tauri-desktopruntime code