How to Set Up the OmniRoute Electron Desktop App: Complete Installation Guide

To set up the OmniRoute Electron desktop app, install dependencies in both the root and electron/ directories, then run npm run dev from the electron/ folder to launch the desktop shell with automatic server spawning.

The OmniRoute Electron wrapper transforms the Next.js web application into a native desktop experience. As implemented in diegosouzapw/OmniRoute, this architecture packages a main process that manages windows and server lifecycle, a secure preload script for IPC communication, and React hooks that let the UI interact with native capabilities without compromising Electron security boundaries.

Prerequisites and Repository Structure

Before starting, ensure you have Node.js 18+ and npm installed. The Electron-related code lives entirely within the electron/ directory at the repository root, while the shared React hooks reside in src/shared/hooks/useElectron.ts.

Key directories to understand:

  • electron/main.js — Main process entry point
  • electron/preload.js — Secure renderer bridge
  • electron/lib/ — Helper utilities for server management
  • electron/assets/ — Icons and UI resources

Development Setup

The fastest way to run the OmniRoute Electron desktop app locally requires two terminal sessions.

Step 1: Start the Next.js Development Server


# From repository root

npm install
npm run dev

This launches the Next.js dev server (default port 20128). The Electron renderer will poll this endpoint until it responds.

Step 2: Launch the Electron Shell


# In a separate terminal

cd electron
npm install
npm run dev

The npm run dev command in electron/package.json concurrently starts Electron and waits for the server health check at http://localhost:20128. The UI appears only after the server reports ready, preventing blank-screen race conditions.

Production and Stand-alone Builds

For distribution, build the Next.js app in standalone mode so the Electron shell can bundle and spawn it internally.

Build the Next.js Standalone Output

npm run build

This creates a self-contained server under .build/next/standalone/ that the Electron main process references via electron/lib/serverUrlResolver.js.

Run Production Mode

cd electron
npm start

The main process in electron/main.js automatically detects whether to spawn the bundled server or connect to a remote instance based on preferences.

Building Platform-Specific Binaries

Generate installable packages for target operating systems:

cd electron

# Current platform

npm run build

# Windows (.exe installer + portable)

npm run build:win

# macOS (universal .dmg)

npm run build:mac

# Linux (.AppImage)

npm run build:linux

Build artifacts appear in dist-electron/ at the repository root. The electron/package.json scripts delegate to electron-builder with platform-specific configurations.

Remote Server Configuration

The OmniRoute Electron desktop app supports connecting to external OmniRoute instances instead of spawning a local server.

Via Tray Menu

  1. Right-click the system tray icon
  2. Select Remote Server → Connect to Remote Server…
  3. Enter the URL (e.g., http://localhost:20128 or http://10.0.0.5:20128)
  4. Save preferences to electron-preferences.json via electron/lib/remoteServerPreferences.js

Via Environment Variable

Override saved preferences for one-off connections:

export OMNIROUTE_REMOTE_URL=http://my-remote-host:20128
cd electron
npm start

The main process checks process.env.OMNIROUTE_REMOTE_URL before consulting persisted preferences, as implemented in the server URL resolution logic.

Security Architecture

The OmniRoute Electron implementation enforces several security best practices:

  • Content-Security-Policy — Applied via session.webRequest.onHeadersReceived in main.js to restrict script-src, connect-src, and other directives
  • Context isolation — The preload script uses contextBridge.exposeInMainWorld with an explicit whitelist (safeInvoke, safeSend, safeOn) rather than direct remote module access
  • IPC cleanup — React hooks like useServerStatus() and usePortChanged() return disposal functions to prevent listener accumulation

The src/shared/hooks/useElectron.ts file implements useSyncExternalStore for zero-re-render status subscriptions, ensuring efficient UI updates when server state changes.

Troubleshooting Common Issues

Symptom Cause Solution
Blank window on startup Server not responding Verify npm run dev is running in root; check port 20128 availability
IPC methods undefined Preload script failure Ensure contextIsolation: true in main.js BrowserWindow options
Remote connection fails URL protocol mismatch Use http:// not https:// for local network addresses
Build produces no output Missing platform dependencies Install electron-builder prerequisites for target OS

Summary

  • Install dependencies separately in repository root and electron/ directory
  • Use npm run dev in both locations for development with hot-reload
  • Build standalone Next.js output with npm run build before production packaging
  • Generate binaries with npm run build:* commands in the electron/ folder
  • Connect to remote servers via tray menu or OMNIROUTE_REMOTE_URL environment variable
  • Reference electron/main.js for window lifecycle, electron/preload.js for secure IPC, and src/shared/hooks/useElectron.ts for UI integration

Frequently Asked Questions

What Node.js version does OmniRoute Electron require?

OmniRoute builds successfully on Node.js 18 LTS and newer. The electron/package.json specifies compatible Electron versions that bundle their own Node runtime, but development tooling in the root relies on system Node.js for the Next.js build pipeline.

Can I run the desktop app without building the Next.js server first?

For development, yes—run npm run dev in the repository root to start the Next.js dev server, then npm run dev in electron/ to attach the desktop shell. For production, you must run npm run build first to generate the standalone server bundle that electron/main.js spawns.

How does the Electron app know when the server is ready?

The main process polls http://localhost:<PORT> with exponential backoff until receiving an HTTP 200 response. Only then does main.js show the BrowserWindow, implemented in the server health monitoring section. This prevents users from seeing a disconnected UI during cold starts.

Where are remote server preferences stored?

Preferences persist to <userData>/electron-preferences.json via electron/lib/remoteServerPreferences.js, using Electron's app.getPath('userData') directory. The OMNIROUTE_REMOTE_URL environment variable takes precedence over this file for temporary overrides.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →