Categories
Featured-Post-Software-EN Software Engineering (EN)

Building a Cross-Platform Desktop Application with Electron: Complete Guide and Best Practices

Auteur n°16 – Martin

By Martin Moraz
Views: 31

Summary – To deliver high-performance, maintainable desktop applications aligned with your web interfaces, Electron.js leverages JavaScript/HTML/CSS and Chromium to provide a modern UI and a native layer via Node.js, while unifying code across Windows, macOS and Linux. Its Main/Renderer architecture coupled with React ensures modularity, resilience and privilege separation, while IPC communication, the system tray, native notifications and deep links optimize interoperability and user engagement. Using electron-builder, backed by code signing and an automated CI/CD pipeline, ensures reliable builds, packaging and incremental updates on every OS.
Solution: set up an open source CI/CD workflow to automate builds, tests, packaging and reliable deployments.

In an environment where desktop solutions must combine performance, easier maintenance, and a user experience consistent with the web, Electron.js emerges as a pragmatic answer for CIOs and IT project managers. By leveraging familiar web technologies—JavaScript, HTML, and CSS—it enables you to create rich, operating-system-independent applications while reducing the learning curve.

This article explains how to combine Electron and React to build a modular desktop application, integrate system notifications via the Tray, handle deep links, and prepare distribution with electron-builder. You’ll also discover Chromium’s performance limits and best practices to optimize your project on Windows, macOS, and Linux.

Why Choose Electron.js for Your Desktop Applications

Electron unifies desktop and web environments, reducing development time and technical complexity. Its Chromium core guarantees a modern interface, while Node.js provides native system access.

Cross-Platform Portability

Electron.js packages your web code in a Chromium container, ensuring identical rendering on Windows, macOS, and Linux. This portability avoids separate development efforts for each OS, significantly cutting costs and deadlines. System API abstraction simplifies file access and native processes without juggling multiple technologies. Finally, maintenance requires only one codebase, making updates and security patches easier to manage.

Example: A Swiss SME specializing in industrial data analysis replaced three separate desktop tools with a single Electron application. This project demonstrated how portability reduces deployment costs and harmonizes the user experience while limiting internal IT maintenance.

Familiar Web Integration

Front-end developers can reuse their JavaScript, HTML, and CSS skills in Electron, avoiding the need to learn desktop-specific languages like C# or Swift. Web frameworks such as React, Vue, or Angular integrate naturally into the Renderer process, offering an ultra-fast development cycle. You benefit from a rich ecosystem and familiar debugging tools without sacrificing native performance.

Moreover, modern UI components—charting libraries, grid systems—work the same whether deployed in a browser or embedded in your desktop application. This optimizes graphical consistency across your web and desktop tools.

Node.js Ecosystem

Electron ships with Node.js, granting access to native modules and system APIs. You can interact with the file system, run background processes, and communicate with external services via sockets. This flexibility is invaluable for automating tasks, managing logs, or orchestrating batch processes directly within your app. Node.js also delivers a vast catalog of open-source libraries, accelerating features like authentication, key management, or encryption.

The npm ecosystem offers hundreds of certified packages, enabling you to build a robust workflow from day one. For instance, the Node Notifier library simplifies sending native notifications without complex development. Discover also the best automation tools to automate, collaborate, and innovate.

Modular Architecture and Integrating React with Electron

A clear separation between the Main and Renderer processes ensures stability and scalability. React brings reusable component structure, simplifying UI evolution.

Main and Renderer Process Structure

Electron distinguishes two execution contexts: the Main process, responsible for windows, application lifecycle, and system APIs; and Renderer processes, which handle UI rendering and user experience. This architecture isolates critical system access and limits the impact of a UI bug on overall stability. Each window maps to a Renderer running in a secure sandbox. Renderer crashes don’t affect the Main process, improving resilience.

To implement this structure, define a main file (e.g., main.js) to initialize the window and load your React bundle. Renderer files import your React code and handle user interactions without risking direct system resource access.

Inter-Process Communication (IPC)

Main and Renderer communicate via the ipcMain and ipcRenderer modules. This secure channel sends asynchronous messages to trigger system actions—file reads, local database access, or notification handling. You can structure these exchanges with named channels for clarity and traceability.

IPC limits Renderer privileges and enhances security. Instead of granting direct file-system access, the Renderer requests the Main process to perform operations and then receives the result.

This separation reduces the attack surface and simplifies code audits by centralizing critical access in the Main process. You can add authentication and permission checks before each sensitive operation.

Modularity and React Components

React encourages creating separate functional or class components, each handling a specific UI portion. Organize your project into modules: dashboard, settings, notifications, etc. Each component can use hooks or emit events to communicate without relying on a global singleton.

This approach facilitates unit testing and continuous integration. Components can be mocked or isolated, improving code quality and accelerating new feature releases. Use tools like Jest or React Testing Library to automatically validate your changes.

By adopting TypeScript, you strengthen module reliability by typing props and state. This reduces runtime bugs and makes your code more readable for new team members.

Edana: strategic digital partner in Switzerland

We support companies and organizations in their digital transformation

Tray Notifications and Deep Links

Tray notifications offer discreet yet engaging interaction without monopolizing the main window. Deep links streamline integration with external processes or web workflows.

Notification System and Tray Icon

The Tray icon maintains a constant presence in the system bar, even when the main application is closed. You can attach a context menu for quick actions: reopen the window, trigger a sync, or display a status. Notifications appear natively, ensuring visual consistency and respecting OS settings.

To implement these notifications, use Electron’s Tray and Notification APIs. Define a Tray instance with an icon, tooltip, and menu. For each event—message arrival, process completion, or alert—you trigger a native notification configurable per platform.

This mechanism keeps users engaged without interrupting their workflow. It’s especially useful for collaborative apps, monitoring tools, or internal messaging.

Example: A Switzerland-based logistics company uses the Tray to automatically inform drivers about delivery statuses, even when the main interface is minimized. This approach has proven effective in reducing response times and improving operational agility.

Deep Link to Open the App from a Browser

Deep links (custom URI scheme) launch the desktop application from a web link or email, passing parameters. This smooths the transition between your online portals and the Electron app, offering an integrated experience. For example, a “myapp://order/1234” link can open the order details page directly in the Renderer.

To configure deep links, declare a custom URI scheme in your app manifest. Electron detects the “open-url” event on macOS or command-line arguments on Windows and Linux. You then retrieve parameters and forward them via IPC to the Renderer to display the correct view.

This feature enhances continuity between your existing systems, reducing user friction and boosting desktop adoption.

Handling Native Events

Beyond notifications and deep links, Electron can capture system events: network changes, USB device disconnection, battery power changes, etc. You can dynamically adapt your app—pause intensive calculations on battery power or resume syncing when the network reconnects.

Manage these events in the Main process with listeners for modules like powerMonitor or systemPreferences. You then send this information to Renderers to show messages or adjust the UI.

Responsive handling of native events improves user experience by adapting to context and constraints.

Building and Distributing with electron-builder

electron-builder simplifies creating installable packages for each platform, with incremental update management. A secure, optimized configuration ensures reliable, high-performance deployments.

electron-builder Configuration

electron-builder relies on a configuration file (package.json or builder.config.js) where you specify OS targets, the icon, application name, and compression options. You can generate .exe for Windows, .dmg for macOS, and AppImage or .deb for Linux. Each target has specific options: code signing, Apple notarization, checksums, etc.

Also define the update channel (stable, beta) and the asset URL for automatic downloads. Electron’s auto-updater integrates directly with releases hosted on a server or CDN, ensuring seamless updates for users.

For reproducible builds, lock builder and dependency versions. Use CI/CD build scripts to run commands in a clean environment, avoiding unwanted files.

Code Signing and Security

Code signing is essential to avoid antivirus alerts and establish trust on macOS and Windows. Obtain certificates from recognized authorities. Electron-builder offers options to inject keys automatically during build.

On macOS, Apple notarization ensures Gatekeeper compliance. Integrate the process into your CI pipeline via actions or scripts. On Windows, EV signing reduces SmartScreen warnings. Remember to encrypt your CI environment variables to protect certificates.

Valid signatures reduce installation friction and reinforce your application’s credibility with users and internal IT teams.

Build Optimization

To limit bundle size, exclude unused dependencies with the asarUnpack option and the files parameter in builder configuration. You can also split code into chunks to reduce initial install size and load heavy modules dynamically.

Enable UPX compression for Windows executables and gzip compression for update server assets. Test startup performance in an environment simulating a slow disk. Adjust splash screen timing and prioritize lazy loading in React to improve perceived performance.

Finally, regularly check Chromium and Node.js versions—each update includes performance optimizations and security patches. Scheduling quarterly builds helps keep your solution current without excessive effort.

Example: A Swiss medtech startup automated its CI pipeline to generate and notarize macOS builds nightly. This workflow proved update reliability and reduced manual interventions by 75%, ensuring continuous delivery compliant with regulatory requirements.

Turn the Web Experience into a Desktop Asset

Electron.js provides a robust framework to port your web interfaces to desktop applications while benefiting from secure, modular native access. The Main/Renderer architecture, combined with React, simplifies maintainability and scalability. Advanced features—Tray, notifications, deep links—boost user engagement and interoperability with existing systems. Finally, electron-builder ensures reliable distribution and updates across platforms.

Our team of experts is ready to guide you through designing, optimizing, and deploying a custom desktop solution. With our open-source, modular, and secure approach, we help you maximize your application’s business value while minimizing technical and operational risks.

Discuss your challenges with an Edana expert

By Martin

Enterprise Architect

PUBLISHED BY

Martin Moraz

Avatar de David Mendes

Martin is a senior enterprise architect. He designs robust and scalable technology architectures for your business software, SaaS products, mobile applications, websites, and digital ecosystems. With expertise in IT strategy and system integration, he ensures technical coherence aligned with your business goals.

FAQ

Frequently Asked Questions about Cross-Platform Electron Desktop

What are the technical prerequisites to start an Electron project with React?

To get started, you will need Node.js and npm (or yarn), the Electron CLI, and a bundler like Webpack or Vite to compile your React code. A solid grasp of JavaScript, HTML, and CSS is essential. Set up a main.js file to initialize the Electron window, an index.html to load your React bundle, and install dependencies via package.json to structure your project.

How should you structure the Main/Renderer architecture to ensure security?

Strictly separate the Main process (system APIs, window management) from the Renderer process (UI). Use ipcMain and ipcRenderer for communication, validating each IPC call to prevent malicious code execution. Restrict the Renderer’s privileges by delegating critical operations to the Main. This isolation minimizes the attack surface and makes auditing your application easier.

What are the best practices for optimizing an Electron application’s performance?

Reduce bundle size using code splitting and asarUnpack, exclude unused modules, and enable UPX compression for Windows. Optimize your React UI with lazy loading of heavy components and prefer memoized hooks (useMemo, useCallback). Monitor CPU/memory usage, regularly update Chromium and Node.js, and test on low-end configurations to ensure fast loading.

How do you handle updates and cross-platform distribution?

Use electron-builder to generate packages (.exe, .dmg, .AppImage/.deb) and configure the autoUpdater module with release channels (stable, beta). Set the hosting URLs for assets and version your app in the configuration file. Integrate these steps into a CI/CD pipeline to automate builds, code signing, and publishing incremental updates.

What pitfalls should you avoid when implementing Tray notifications and deep links?

Check icon formats and native behaviors per platform. Handle the open-url event (macOS) and command-line arguments (Windows/Linux) for deep links, always validating incoming parameters. Avoid excessive IPC loops and predefine named channels to clarify interactions between the Tray and Renderers.

How do you ensure code signing and compliance on macOS and Windows?

Obtain certificates from a recognized authority and configure electron-builder to inject your keys during the build phase. On macOS, automate Apple notarization to satisfy Gatekeeper. On Windows, choose an EV signature to reduce SmartScreen warnings. Secure your environment variables in the CI/CD system to protect access to certificates.

Which key metrics should you track to evaluate an Electron desktop application’s success?

Track adoption rate (active installations), usage frequency, crash rates, and update failures. Measure startup time, memory/CPU consumption, and user feedback on UX. Analyze logs to detect errors, and adjust your KPIs according to business goals (productivity, responsiveness, engagement).

How can you minimize bundle size and speed up application startup?

Exclude unnecessary dependencies using the files parameter and organize your code into dynamic chunks. Enable gzip compression for update assets and UPX for Windows executables. Use asar to bundle resources and load heavy modules on demand. Regularly test startup performance on slow disks to fine-tune your splash screen.

CONTACT US

They trust us for their digital transformation

Let’s talk about you

Describe your project to us, and one of our experts will get back to you.

SUBSCRIBE

Don’t miss our strategists’ advice

Get our insights, the latest digital strategies and best practices in digital transformation, innovation, technology and cybersecurity.

Let’s turn your challenges into opportunities

Based in Geneva, Edana designs tailor-made digital solutions for companies and organizations seeking greater competitiveness.

We combine strategy, consulting, and technological excellence to transform your business processes, customer experience, and performance.

Let’s discuss your strategic challenges.

022 596 73 70

Agence Digitale Edana sur LinkedInAgence Digitale Edana sur InstagramAgence Digitale Edana sur Facebook