{"id":884,"date":"2026-07-02T06:12:38","date_gmt":"2026-07-01T23:12:38","guid":{"rendered":"https:\/\/sumberlaba.com\/index.php\/2026\/07\/02\/building-cross-platform-desktop-applications-with-electron-the-ultimate-step-by-step-guide\/"},"modified":"2026-07-02T06:12:38","modified_gmt":"2026-07-01T23:12:38","slug":"building-cross-platform-desktop-applications-with-electron-the-ultimate-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/sumberlaba.com\/index.php\/2026\/07\/02\/building-cross-platform-desktop-applications-with-electron-the-ultimate-step-by-step-guide\/","title":{"rendered":"Building Cross-Platform Desktop Applications with Electron: The Ultimate Step-by-Step Guide"},"content":{"rendered":"<h1>Building Cross-Platform Desktop Applications with Electron: The Ultimate Step-by-Step Guide<\/h1>\n<p>In the ever-evolving landscape of software development, the ability to create desktop applications that run seamlessly on Windows, macOS, and Linux using web technologies has become a game changer. Electron, an open-source framework developed by GitHub, empowers developers to build native-like desktop apps with HTML, CSS, and JavaScript, leveraging the power of Chromium and Node.js. Whether you are a seasoned web developer looking to expand your skillset or a newcomer eager to create your first desktop tool, understanding Electron is essential. This guide will walk you through everything you need to know\u2014from the fundamental architecture to advanced optimizations\u2014so you can ship a polished, production-ready application.<\/p>\n<p>Electron has powered some of the most popular applications in the world, including Visual Studio Code, Slack, Discord, and Figma. Its appeal lies in its ability to reuse existing web codebases, access native operating system APIs, and deliver a consistent user experience across platforms. However, building with Electron also comes with challenges, such as managing renderer processes, handling security concerns, and optimizing performance. In this comprehensive tutorial, you will learn not only how to set up your first Electron project but also how to structure a professional application, implement inter-process communication (IPC), package your app for distribution, and follow best practices to avoid common pitfalls. By the end of this article, you\u2019ll be equipped with the knowledge to create your own desktop applications with confidence.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/via.placeholder.com\/800x600\/4a90d9\/ffffff?text=how%20to%20use%20Electron%20for%20desktop%20apps\" alt=\"Article illustration\" style=\"display:block;margin:20px auto;max-width:100%;height:auto;border-radius:8px;\" \/><\/p>\n<h2>Understanding Electron\u2019s Core Architecture<\/h2>\n<p>Before diving into code, it is crucial to understand how Electron works under the hood. Electron applications consist of two main types of processes: the main process and renderer processes. The main process runs the application\u2019s entry point (typically <code>main.js<\/code>) and has full access to Node.js APIs, allowing it to interact with the file system, create native menus, spawn child processes, and manage the application lifecycle. Each window your application opens runs in its own renderer process, which is essentially a Chromium browser instance. Renderer processes render your web content (HTML, CSS, JavaScript) and can also access some Node.js APIs through a context bridge or preload scripts, but for security reasons, direct access to Node.js in renderers is disabled by default in modern Electron versions.<\/p>\n<p>Communication between these processes is handled via Electron\u2019s inter-process communication (IPC) module. The main process can send and receive messages using <code>ipcMain<\/code>, while renderer processes use <code>ipcRenderer<\/code>. This design ensures that the UI remains responsive while the main process handles system-level tasks. Additionally, Electron includes a preload script\u2014a JavaScript file that runs before the renderer process loads\u2014that can expose specific APIs from the main process to the renderer in a controlled manner. Understanding this architecture is foundational because every decision you make\u2014from file I\/O to window management\u2014will involve these processes. For instance, if you need to read a file from disk and display its contents in the UI, you must send an IPC message from the renderer to the main process, which performs the file operation and sends the data back. This separation prevents the UI thread from blocking and maintains security boundaries.<\/p>\n<h2>Step 1: Setting Up Your Development Environment<\/h2>\n<p>To begin building with Electron, you need Node.js installed on your machine. Visit <a href=\"https:\/\/nodejs.org\">nodejs.org<\/a> and download the LTS version. Once installed, open a terminal or command prompt and verify the installation with <code>node -v<\/code> and <code>npm -v<\/code>. You should see version numbers. Next, create a new directory for your project and navigate into it:<\/p>\n<pre><code>mkdir my-electron-app\ncd my-electron-app<\/code><\/pre>\n<p>Initialise a new npm project by running <code>npm init -y<\/code>. This creates a <code>package.json<\/code> file. Now install Electron as a development dependency:<\/p>\n<pre><code>npm install electron --save-dev<\/code><\/pre>\n<p>This command will download the Electron binaries. Depending on your operating system, this may take a few minutes. After installation, open the <code>package.json<\/code> file and modify the <code>\"main\"<\/code> field to point to your main process file. Create that file by adding a <code>\"main\": \"main.js\"<\/code> entry. Also update the <code>\"scripts\"<\/code> section to include a start command: <code>\"start\": \"electron .\"<\/code>. Your <code>package.json<\/code> should look like this:<\/p>\n<pre><code>{\n  \"name\": \"my-electron-app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"main.js\",\n  \"scripts\": {\n    \"start\": \"electron .\"\n  },\n  \"devDependencies\": {\n    \"electron\": \"^28.0.0\"\n  }\n}<\/code><\/pre>\n<p>Now create the main process file, <code>main.js<\/code>, in your project root. This file will create a BrowserWindow and load an HTML file. Start with this minimal code:<\/p>\n<pre><code>const { app, BrowserWindow } = require('electron');\nconst path = require('path');\n\nfunction createWindow() {\n  const win = new BrowserWindow({\n    width: 800,\n    height: 600,\n    webPreferences: {\n      preload: path.join(__dirname, 'preload.js'),\n      nodeIntegration: false,\n      contextIsolation: true\n    }\n  });\n  win.loadFile('index.html');\n}\n\napp.whenReady().then(() => {\n  createWindow();\n  app.on('activate', () => {\n    if (BrowserWindow.getAllWindows().length === 0) createWindow();\n  });\n});\n\napp.on('window-all-closed', () => {\n  if (process.platform !== 'darwin') app.quit();\n});<\/code><\/pre>\n<p>Create an <code>index.html<\/code> file with a simple \u201cHello Electron\u201d message, and a <code>preload.js<\/code> file (even if empty). Run <code>npm start<\/code> to see your first Electron window. Congratulations\u2014you have a working desktop app!<\/p>\n<h2>Step 2: Structuring a Real-World Electron Application<\/h2>\n<p>As your application grows, keeping everything in a single directory becomes unmanageable. A well-organised project structure is essential for maintainability, especially when you have multiple windows, services, and assets. A common pattern is to separate your main process code, renderer code, and preload scripts into distinct folders. Here is a recommended structure:<\/p>\n<ul>\n<li><code>package.json<\/code><\/li>\n<li><code>main.js<\/code> \u2013 entry point for main process<\/li>\n<li><code>preload.js<\/code> \u2013 preload script for renderer<\/li>\n<li><code>src\/<\/code> \u2013 main source code\n<ul>\n<li><code>main\/<\/code> \u2013 main process modules (e.g., menu, updater, IPC handlers)<\/li>\n<li><code>renderer\/<\/code> \u2013 renderer code (HTML, CSS, JS)<\/li>\n<li><code>preload\/<\/code> \u2013 any additional preload scripts<\/li>\n<li><code>shared\/<\/code> \u2013 code used by both main and renderer (constants, types)<\/li>\n<\/ul>\n<\/li>\n<li><code>assets\/<\/code> \u2013 images, fonts, icons<\/li>\n<li><code>build\/<\/code> \u2013 build configuration<\/li>\n<li><code>dist\/<\/code> \u2013 packaged application output<\/li>\n<\/ul>\n<p>In the renderer folder, you may want to use a modern front-end framework like React, Vue, or Angular. Electron does not force you to use any particular library, but integrating a framework can streamline UI development. For example, if you use React, set up your project with <code>create-react-app<\/code> and then modify the <code>main.js<\/code> to load your React app\u2019s <code>build\/index.html<\/code>. You can also use Electron Forge or Electron Builder to scaffold a project with built-in tooling. I highly recommend using Electron Forge (<code>npm init electron-app@latest my-app -- --template=vite<\/code>) for new projects because it provides hot reloading, packaging, and publishing out of the box. However, for this tutorial, we stick with manual setup to give you a deeper understanding.<\/p>\n<p>When structuring your project, pay attention to how you handle IPC calls. Create separate files for each major feature (e.g., <code>src\/main\/file-handlers.js<\/code>, <code>src\/main\/database.js<\/code>) and use a central <code>ipc-main.js<\/code> to register all listeners. In the renderer, create a utility module that wraps <code>ipcRenderer<\/code> calls. This separation makes your code testable and scalable.<\/p>\n<h2>Step 3: Implementing Inter-Process Communication (IPC)<\/h2>\n<p>IPC is the backbone of any Electron application. Without it, your renderer cannot request data from the system or access Node.js APIs. Electron provides two IPC modules: <code>ipcMain<\/code> for the main process and <code>ipcRenderer<\/code> for the renderer. The typical communication pattern is request-response or one-way messages. You can use the <code>invoke<\/code>\/<code>handle<\/code> pattern for request-response, which returns a Promise. Let\u2019s implement a simple example: reading a file from disk when the user clicks a button.<\/p>\n<p>First, in your preload script (<code>preload.js<\/code>), expose a safe API to the renderer using <code>contextBridge<\/code>. This is a secure method that prevents the renderer from directly accessing Node.js:<\/p>\n<pre><code>const { contextBridge, ipcRenderer } = require('electron');\n\ncontextBridge.exposeInMainWorld('electronAPI', {\n  readFile: (filePath) = ipcRenderer.invoke('read-file', filePath)\n});<\/code><\/pre>\n<p>Now in the main process, register a handler for the <code>read-file<\/code> channel:<\/p>\n<pre><code>const { ipcMain, dialog } = require('electron');\nconst fs = require('fs');\n\nipcMain.handle('read-file', async (event, filePath) => {\n  try {\n    const data = await fs.promises.readFile(filePath, 'utf-8');\n    return { success: true, data };\n  } catch (err) {\n    return { success: false, error: err.message };\n  }\n});<\/code><\/pre>\n<p>In your renderer HTML\/JS, you can call this function when a button is clicked:<\/p>\n<pre><code>document.getElementById('loadBtn').addEventListener('click', async () => {\n  const result = await window.electronAPI.readFile('\/path\/to\/file.txt');\n  if (result.success) {\n    document.getElementById('output').textContent = result.data;\n  } else {\n    console.error('Error:', result.error);\n  }\n});<\/code><\/pre>\n<p>Always use the preload script with <code>contextIsolation: true<\/code> and <code>nodeIntegration: false<\/code> to prevent security vulnerabilities. Never use <code>enableRemoteModule<\/code> or disable contextIsolation unless you fully understand the risks. Modern Electron (v12+) defaults to these secure settings. Also note that the <code>remote<\/code> module has been deprecated; use IPC instead.<\/p>\n<p>For one-way messages, use <code>send<\/code>\/<code>on<\/code> patterns. For example, you might want to notify the main process when the user changes a setting. The same security principles apply.<\/p>\n<h2>Step 4: Creating Native Menus and Dialogues<\/h2>\n<p>A desktop application without a native menu feels incomplete. Electron makes it easy to create custom application menus using the <code>Menu<\/code> module. Typically, you build the menu in the main process and set it as the application menu. You can also create context menus for specific elements in the renderer. Let\u2019s walk through creating a standard menu with File, Edit, and Help submenus.<\/p>\n<p>In your <code>main.js<\/code>, after the app is ready, create the menu template:<\/p>\n<pre><code>const { Menu } = require('electron');\n\nconst template = [\n  {\n    label: 'File',\n    submenu: [\n      { role: 'quit' }\n    ]\n  },\n  {\n    label: 'Edit',\n    submenu: [\n      { role: 'undo' },\n      { role: 'redo' },\n      { type: 'separator' },\n      { role: 'cut' },\n      { role: 'copy' },\n      { role: 'paste' }\n    ]\n  },\n  {\n    label: 'Help',\n    submenu: [\n      {\n        label: 'About',\n        click: () => {\n          dialog.showMessageBox({ type: 'info', message: 'My Electron App v1.0' });\n        }\n      }\n    ]\n  }\n];\n\nconst menu = Menu.buildFromTemplate(template);\nMenu.setApplicationMenu(menu);<\/code><\/pre>\n<p>For a native look, you can use macOS-specific roles like <code>'hide'<\/code> and <code>'hideOthers'<\/code>. Electron also supports accelerators (keyboard shortcuts) via the <code>accelerator<\/code> property. For example, <code>accelerator: 'CmdOrCtrl+S'<\/code>. To build a context menu (right-click), you need to send an IPC message from the renderer to the main process:<\/p>\n<pre><code>\/\/ In preload.js\ncontextBridge.exposeInMainWorld('electronAPI', {\n  showContextMenu: () = ipcRenderer.send('show-context-menu')\n});\n\n\/\/ In main.js\nipcMain.on('show-context-menu', (event) => {\n  const template = [\n    { label: 'Reload', role: 'reload' },\n    { label: 'DevTools', role: 'toggleDevTools' }\n  ];\n  const menu = Menu.buildFromTemplate(template);\n  menu.popup({ window: BrowserWindow.fromWebContents(event.sender) });\n});<\/code><\/pre>\n<p>In the renderer, attach a <code>contextmenu<\/code> event listener to the element or document:<\/p>\n<pre><code>document.addEventListener('contextmenu', (e) => {\n  e.preventDefault();\n  window.electronAPI.showContextMenu();\n});<\/code><\/pre>\n<p>You can also create custom dialogs (open file, save file, message boxes) using the <code>dialog<\/code> module. These synchronous dialogs block the renderer, so always call them from the main process via IPC. For example, to let the user select a file:<\/p>\n<pre><code>ipcMain.handle('open-file-dialog', async (event) => {\n  const result = await dialog.showOpenDialog({ properties: ['openFile'] });\n  if (!result.canceled) {\n    return result.filePaths[0];\n  }\n  return null;\n});<\/code><\/pre>\n<h2>Step 5: Packaging and Distributing Your Application<\/h2>\n<p>Once your application is ready, you need to package it into an executable that users can install and run without requiring Node.js. Electron does not include a built-in packager, but there are excellent third-party tools: <strong>electron-builder<\/strong> and <strong>Electron Forge<\/strong>. In this guide, we will use electron-builder because it offers great flexibility for Windows, macOS, and Linux packaging.<\/p>\n<p>First, install electron-builder as a dev dependency:<\/p>\n<pre><code>npm install electron-builder --save-dev<\/code><\/pre>\n<p>Then, add a <code>\"build\"<\/code> configuration to your <code>package.json<\/code>. At minimum, you need to specify the app ID, product name, and icon paths. Here is a sample configuration that works for all platforms:<\/p>\n<pre><code>{\n  \"build\": {\n    \"appId\": \"com.example.my-electron-app\",\n    \"productName\": \"MyElectronApp\",\n    \"directories\": {\n      \"output\": \"dist\"\n    },\n    \"files\": [\n      \"main.js\",\n      \"preload.js\",\n      \"index.html\",\n      \"src\/**\/*\"\n    ],\n    \"win\": {\n      \"icon\": \"assets\/icon.ico\",\n      \"target\": \"nsis\"\n    },\n    \"mac\": {\n      \"icon\": \"assets\/icon.icns\",\n      \"target\": \"dmg\"\n    },\n    \"linux\": {\n      \"icon\": \"assets\/icon.png\",\n      \"target\": \"AppImage\"\n    }\n  }\n}<\/code><\/pre>\n<p>Add a build script to your <code>package.json<\/code> scripts section: <code>\"build\": \"electron-builder\"<\/code>. Also ensure you have an icon in the specified formats. You can generate icons from a PNG using online tools or the <code>electron-icon-maker<\/code> package. Run <code>npm run build<\/code>. Electron-builder will create installers in the <code>dist\/<\/code> folder. For Windows, you get an .exe (NSIS installer); for macOS, a .dmg; for Linux, an .AppImage. You can further customise options like auto-update, code signing, and publishing to GitHub Releases or the Mac App Store.<\/p>\n<p>For auto-updates, integrate <code>electron-updater<\/code> (by the electron-builder team). It checks a remote server for new versions and downloads them transparently. This is essential for production apps.<\/p>\n<h2>Best Practices and Tips for Electron Development<\/h2>\n<h3>1. Always Enable Context Isolation and Disable Node Integration<\/h3>\n<p>Security should be your top priority. Never use <code>nodeIntegration: true<\/code> in webPreferences. Instead, use a preload script with <code>contextBridge<\/code> to expose only the APIs you need. This prevents malicious scripts from accessing Node.js. Also, set <code>webSecurity: true<\/code> and consider using <code>Content-Security-Policy<\/code> headers in your HTML to mitigate XSS attacks.<\/p>\n<h3>2. Keep the Main Process Lightweight<\/h3>\n<p>The main process is single-threaded and blocks the UI if you perform heavy synchronous operations. Offload CPU-intensive tasks to a separate Node.js child process or use worker threads. For I\/O operations, always use asynchronous APIs (e.g., <code>fs.promises<\/code>). If you must perform a long task, consider sending progress updates back to the renderer via IPC.<\/p>\n<h3>3. Use BrowserWindow Wisely to Manage Memory<\/h3>\n<p>Each window consumes a separate Chromium renderer process, which can be memory-heavy. For performance, limit the number of open windows. If you need a persistent background process, consider using a hidden BrowserWindow or a <code>ServiceWorker<\/code> (Chromium supports it). Also, set <code>backgroundThrottling: false<\/code> if your app needs to continue running when minimised. Monitor memory usage with the Chrome Dev Tools (accessible via <code>win.webContents.openDevTools()<\/code>).<\/p>\n<h3>4. Implement a Splash Screen for Slow Startups<\/h3>\n<p>Electron apps can take a moment to initialise, especially on first launch. Show a simple splash window (a BrowserWindow with no frame and a logo) while your main window loads. After the main window\u2019s <code>did-finish-load<\/code> event, close the splash and show the main window.<\/p>\n<h3>5. Use the Right Package for Notifications and Tray Icons<\/h3>\n<p>To create a system tray icon, use Electron\u2019s <code>Tray<\/code> module. For native notifications, use <code>Notification<\/code> API in the renderer (if permission granted) or the <code>Notification<\/code> module in the main process. Both work across platforms.<\/p>\n<h2>FAQ: Frequently Asked Questions About Electron<\/h2>\n<h3>Q1: Is Electron good for building desktop apps? What are its limitations?<\/h3>\n<p>Electron is excellent for apps that need to run on multiple platforms with a web-based UI. Its main limitation is resource usage: each Electron app bundles a full Chromium engine, making the app size large (typically 100-200 MB) and memory consumption higher than native apps. However, for many use cases (like code editors, chat apps, productivity tools), the trade-off is acceptable. Recent improvements like <code>--disable-gpu-sandbox<\/code> and GPU process management help reduce footprint.<\/p>\n<h3>Q2: Can I use web frameworks like React or Vue with Electron?<\/h3>\n<p>Absolutely. Electron is just a wrapper around Chromium, so any front-end framework works. You can set up a build pipeline (Webpack, Vite) that outputs static files to your renderer folder. Many developers use <code>electron-vite<\/code> for seamless integration. Just ensure that your framework\u2019s development server runs on a local port and you load that URL in Electron during development, then switch to loading the built files for production.<\/p>\n<h3>Q3: How do I handle file system access securely?<\/h3>\n<p>Expose only specific file operations through your preload script. Never let the renderer receive arbitrary file paths from user input. Use <code>dialog.showOpenDialog<\/code> to get file paths from the user, then validate them in the main process. Use absolute paths and restrict directories if possible. For reading application data (like user preferences), use Electron\u2019s <code>app.getPath('userData')<\/code> to avoid path traversal vulnerabilities.<\/p>\n<h3>Q4: What is the best way to manage multiple windows in Electron?<\/h3>\n<p>Track your window instances in an array or a Map. Use the <code>win.on('closed')<\/code> event to remove references (avoid memory leaks). For window-to-window communication, use the main process as a relay: both windows send IPC messages to the main process, which forwards them to the other window. Alternatively, you can use <code>webContents.send()<\/code> on the target window. Avoid sharing renderer processes.<\/p>\n<h3>Q5: How do I implement auto-updates in Electron?<\/h3>\n<p>Use the <code>electron-updater<\/code> package from the electron-builder ecosystem. Set up a server (like GitHub Releases, S3, or your own) that hosts the latest installer. In your main process:<\/p>\n<pre><code>const { autoUpdater } = require('electron-updater');\nautoUpdater.checkForUpdatesAndNotify();\nautoUpdater.on('update-available', () => {\n  \/\/ Notify user\n});\nautoUpdater.on('download-progress', (progress) => {\n  \/\/ Update progress bar\n});\nautoUpdater.on('update-downloaded', () => {\n  autoUpdater.quitAndInstall();\n});<\/code><\/pre>\n<p>You need to sign your builds for macOS and set the publisher for Windows to avoid SmartScreen warnings.<\/p>\n<h3>Q6: Can I access native Node.js modules (like native addons) in Electron?<\/h3>\n<p>Yes, but they must be compiled against the exact Electron Node.js version. Use <code>electron-rebuild<\/code> (part of the Electron ecosystem) to recompile native modules automatically. Add it as a postinstall script in <code>package.json<\/code>.<\/p>\n<h2>Conclusion: What\u2019s Next?<\/h2>\n<p>Electron empowers you to create desktop applications with the tools you already know\u2014JavaScript, HTML, and CSS. This tutorial covered the essential steps: setting up the environment, understanding the two-process architecture, structuring a real project, implementing IPC, building native menus, and packaging for distribution. You also learned critical security and performance best practices. With this foundation, you can now explore advanced features like custom title bars, multi-threading via worker threads, WebGPU acceleration, and integration with native APIs (Notification, Tray, PowerMonitor). The Electron ecosystem is vast, with libraries for everything from SQLite databases to automatic updates. As you build, remember to profile your app\u2019s performance using Chromium DevTools and always test on all target platforms. The future of desktop development is hybrid, and Electron is a robust choice. Now go build something amazing.<\/p>\n<h2>Reference Tables<\/h2>\n<table border=\"1\" cellpadding=\"8\">\n<caption>Table 1: Comparison of Electron Packaging Tools<\/caption>\n<thead>\n<tr>\n<th>Feature<\/th>\n<th>Electron Forge<\/th>\n<th>Electron Builder<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Init CLI<\/td>\n<td>Yes (includes templates)<\/td>\n<td>No (manual setup)<\/td>\n<\/tr>\n<tr>\n<td>Auto-updates<\/td>\n<td>Built-in via electron-forge<\/td>\n<td>Via electron-updater (separate package)<\/td>\n<\/tr>\n<tr>\n<td>Code signing<\/td>\n<td>Manual configuration<\/td>\n<td>Built-in support for macOS and Windows<\/td>\n<\/tr>\n<tr>\n<td>Target formats<\/td>\n<td>DMG, NSIS, AppImage, Snap, etc.<\/td>\n<td>Same plus .pkg, .msi, deb, rpm<\/td>\n<\/tr>\n<tr>\n<td>Hot reload<\/td>\n<td>Yes (with Vite\/Webpack plugins)<\/td>\n<td>Not built-in (use third-party)<\/td>\n<\/tr>\n<tr>\n<td>Ease of use<\/td>\n<td>Beginner friendly<\/td>\n<td>More control, steeper learning curve<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table border=\"1\" cellpadding=\"8\">\n<caption>Table 2: Common Electron IPC Patterns<\/caption>\n<thead>\n<tr>\n<th>Pattern<\/th>\n<th>Main Process API<\/th>\n<th>Renderer Process API<\/th>\n<th>Use Case<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Request-Response<\/td>\n<td>ipcMain.handle(channel, handler)<\/td>\n<td>ipcRenderer.invoke(channel, &#8230;args)<\/td>\n<td>Read file, database query<\/td>\n<\/tr>\n<tr>\n<td>One-way (main to renderer)<\/td>\n<td>win.webContents.send(channel, data)<\/td>\n<td>ipcRenderer.on(channel, listener)<\/td>\n<td>Menu command, system event<\/td>\n<\/tr>\n<tr>\n<td>One-way (renderer to main)<\/td>\n<td>ipcMain.on(channel, listener)<\/td>\n<td>ipcRenderer.send(channel, data)<\/td>\n<td>Logging, UI state change<\/td>\n<\/tr>\n<tr>\n<td>Broadcast (main to all windows)<\/td>\n<td>BrowserWindow.getAllWindows().forEach(w => w.webContents.send(&#8230;))<\/td>\n<td>Same as above<\/td>\n<td>Global notifications, theme changes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>Building Cross-Platform Desktop Applications with Electron: The Ultimate Step-by-Step Guide In the ever-evolving landscape of software development, the ability to create desktop applications that run seamlessly on Windows, macOS, and Linux using web technologies has become a game changer. Electron, an open-source framework developed by GitHub, empowers developers to build native-like desktop apps with HTML, &hellip; <\/p>\n","protected":false},"author":2716,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-884","post","type-post","status-publish","format-standard","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/posts\/884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/users\/2716"}],"replies":[{"embeddable":true,"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/comments?post=884"}],"version-history":[{"count":0,"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/posts\/884\/revisions"}],"wp:attachment":[{"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/media?parent=884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/categories?post=884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sumberlaba.com\/index.php\/wp-json\/wp\/v2\/tags?post=884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}