Skip to main content
The Bitwarden Desktop app is built on Electron, which uses a multi-process architecture. Understanding this architecture is critical for developing the desktop app correctly.

Electron Multi-Process Architecture

Electron applications run in two distinct process types:

Main Process

Location: /apps/desktop/src/main/ Entry Point: /apps/desktop/src/main.ts The main process:
  • Runs Node.js with full system access
  • Has access to all Electron APIs
  • Manages application lifecycle
  • Creates and controls browser windows
  • Handles native integrations (file system, OS APIs, etc.)
  • Cannot import Angular or browser-only code
Key responsibilities:

Renderer Process

Location: /apps/desktop/src/app/ Entry Point: /apps/desktop/src/app/main.ts (Angular bootstrap) The renderer process:
  • Runs Chromium (browser environment)
  • Hosts the Angular application
  • Has limited system access (sandboxed)
  • Cannot directly import Node.js modules
  • Cannot directly use Electron main process APIs
Environment: Standard web application with Angular, running in a Chromium-based browser window.
CRITICAL RULE: Never import Node.js modules directly in the renderer process!This will cause runtime errors because Node.js APIs are not available in the browser environment. Use preload scripts or IPC instead.

Preload Scripts

Location: /apps/desktop/src/preload.ts and feature-specific preload files Preload scripts are the bridge between main and renderer processes. They:
  • Run before the renderer process loads
  • Have access to both Node.js and browser APIs
  • Expose safe APIs to the renderer via contextBridge
  • Are the only way to safely expose Node.js functionality to the renderer

Main Preload Structure

Feature-Specific Preload Example

Inter-Process Communication (IPC)

Electron provides IPC mechanisms for communication between processes:

IPC Invoke (Request-Response)

Best for: Operations that return a value Renderer → Main:

IPC Send (One-Way)

Best for: Fire-and-forget notifications Renderer → Main:

IPC Send from Main to Renderer

Main → Renderer:

Context Isolation

Electron uses context isolation for security:
  • Renderer process code runs in an isolated context
  • Direct access to Electron/Node.js APIs is blocked
  • Only APIs explicitly exposed via contextBridge are available
Never disable context isolation! This is a critical security feature. Always use contextBridge to expose APIs.

Service Architecture

Main Process Services

Services in the main process handle system-level operations:

Renderer Process Services

Angular services in the renderer process:

State Management

State is managed differently in each process:

Main Process State

Renderer Process State

  • Angular services and dependency injection
  • RxJS for reactive state
  • Shared state providers from @bitwarden/state-internal

Cross-Process State Synchronization

Use IPC to synchronize state:

Native Module Integration

Rust native modules are loaded in the main process only:
See Native Modules for detailed information.

Security Considerations

Principle of Least Privilege

  • Renderer process is sandboxed and has minimal privileges
  • Main process has full system access
  • Only expose necessary APIs through preload scripts

Input Validation

Secure IPC Channels

Process Lifecycle

Application Startup

  1. Main process starts (main.ts)
  2. Services are initialized (storage, crypto, etc.)
  3. Window is created (WindowMain)
  4. Preload script runs (before renderer)
  5. Renderer process starts (Angular app)
  6. Angular application bootstraps
  7. IPC communication established

Application Shutdown

  1. User triggers quit
  2. Main process emits before-quit event
  3. Cleanup handlers run
  4. Windows are closed
  5. Main process exits

Process Communication Patterns

Pattern 1: Simple Request-Response

Pattern 2: Event Broadcasting

Pattern 3: Bidirectional Communication

Critical Development Rules

Main Process Context:
  • ✅ Can import Node.js modules
  • ✅ Can import Electron main process APIs
  • ✅ Can import Rust N-API modules
  • ❌ Cannot import Angular modules
  • ❌ Cannot import browser-only code
Renderer Process Context:
  • ✅ Can import Angular modules
  • ✅ Can import browser APIs
  • ✅ Can use window.ipc exposed by preload
  • ❌ Cannot import Node.js modules
  • ❌ Cannot import Electron APIs directly
  • ❌ Cannot import Rust N-API modules directly
Preload Script Context:
  • ✅ Can import Electron’s ipcRenderer and contextBridge
  • ✅ Can import Node.js modules
  • ✅ Bridge between main and renderer
  • ❌ Should not import large libraries
  • ❌ Cannot import Angular

Debugging

Main Process

Renderer Process

Use Chrome DevTools (automatically available in development):

IPC Messages

Log IPC messages for debugging: