IPC Channels Between Electron Renderer and Main Process in Modly: Complete Reference

Modly implements a typed preload bridge where domain-specific API objects exposed to the React renderer route method calls to specific IPC channels handled in the main process via ipcMain.handle and ipcMain.on.

Modly is an Electron-based 3D content creation platform that relies on structured inter-process communication to coordinate between its React frontend and Node.js backend capabilities. Understanding the IPC channels between the Electron renderer and main process in Modly reveals how the application manages window controls, file system operations, model downloads, and Python backend integration. The implementation centers on a strongly-typed preload bridge defined in electron/preload/electron-api.ts that maps high-level JavaScript methods to low-level Electron IPC calls, with corresponding handlers registered in electron/main/ipc-handlers.ts.

The Preload Bridge Architecture

Modly follows Electron's best practices for context isolation by using a preload script to safely expose main process capabilities to the renderer. The architecture consists of three core files:

Each domain-specific namespace (window, filesystem, models, extensions) maps to a set of explicit channel strings following the pattern domain:action.

Window Control IPC Channels

Window management uses a mix of fire-and-forget events and state queries:

Channel Direction Handler Type Source Location
window:minimize Renderer → Main ipcMain.on electron/main/ipc-handlers.ts
window:maximize Renderer → Main ipcMain.on electron/main/ipc-handlers.ts
window:close Renderer → Main ipcMain.on electron/main/ipc-handlers.ts
window:isMaximized Renderer → Main ipcMain.handle electron/main/ipc-handlers.ts
window:maximizeChanged Main → Renderer ipcRenderer.on electron/preload/electron-api.ts

The window:isMaximized channel uses invoke to return a boolean promise, while window:maximizeChanged is a main-to-renderer event for state synchronization.

File System and Dialog IPC Channels

The filesystem API provides comprehensive file and directory operations:

  • fs:selectImage – Opens image picker dialog
  • fs:selectMeshFile – Opens 3D mesh file picker
  • fs:selectDirectory – Opens directory picker with default path
  • fs:selectTextFile – Opens text file picker
  • fs:saveModel – Saves model with dialog
  • fs:savePath – Gets save path dialog
  • fs:readFileBase64 – Reads file as base64
  • fs:readScreenshotDataUrl – Reads screenshot data
  • fs:listDir – Lists directory contents
  • fs:listFiles – Lists files in directory
  • fs:moveDirectory – Moves directories between locations
  • fs:deleteDirectory – Removes directories recursively

All filesystem channels use ipcMain.handle for request-response patterns, returning promises that resolve to file paths or data.

Model Management IPC Channels

Model operations handle downloads, exports, and lifecycle management:

Channel Pattern Purpose
model:listDownloaded Invoke List cached models
model:isDownloaded Invoke Check if specific model exists
model:download Invoke Start model download
model:pauseDownload Invoke Pause active download
model:cancelDownload Invoke Cancel download job
model:delete Invoke Remove downloaded model
model:unloadAll Invoke Clear all loaded models
model:showInFolder Invoke Open model location in system file manager
model:export Invoke Export model to format
model:downloadProgress Event Push updates from main to renderer

The model:downloadProgress channel uses event.sender.send from the main process to stream progress updates to the renderer, which listens via ipcRenderer.on in the preload bridge.

Extension System IPC Channels

Extensions support installation, management, and process execution:

  • extensions:list – List installed extensions
  • extensions:installFromGitHub – Install from GitHub URL
  • extensions:installFromLocal – Install from local path
  • extensions:uninstall – Remove extension
  • extensions:repair – Repair corrupted extension
  • extensions:reload – Reload extension without restart
  • extensions:runProcess – Execute extension subprocess
  • extensions:installProgress – Event channel for installation feedback

The extensions:installProgress event provides real-time feedback during GitHub installations, streaming progress from the main process handler to the React UI.

Python Backend Bridge Channels

Modly integrates a Python FastAPI backend using dedicated IPC channels:

Channel Direction Purpose
python:start Invoke Spawn Python process
python:status Invoke Check if Python backend is running
python:crashed Main → Renderer Notify of Python process crash
python:log Main → Renderer Stream Python stdout/stderr logs

The python:start handler in electron/main/ipc-handlers.ts manages the Python subprocess lifecycle, while python:crashed and python:log push events from main to renderer for monitoring backend health.

System, Settings, and Utility Channels

System Information

  • system:memory – Returns total, used, and available memory via ipcMain.handle

Application Settings

  • settings:get – Retrieve configuration value
  • settings:set – Persist configuration change

Cache Management

  • cache:clear – Clear application cache directories

Auto-updater

  • updater:check – Check for application updates
  • updater:quitAndInstall – Apply update and restart
  • updater:applying – Event indicating update in progress
  • updater:major-minor-available – Event for version availability

Logging

  • log:error – Send error logs from renderer to main
  • log:getPath – Get log file location
  • log:readAll – Read complete log contents
  • log:listSessions – List available log sessions

First-Run Setup

  • setup:check – Verify first-run status
  • setup:saveDataDir – Persist data directory selection
  • setup:run – Execute setup workflow
  • setup:progress – Event for setup step updates
  • setup:complete – Event signaling setup finished
  • setup:error – Event for setup failures

Workspace Management

  • workspace:listCollections – List project collections
  • workspace:createCollection – Create new collection
  • workspace:renameCollection – Rename existing collection
  • workspace:deleteCollection – Remove collection
  • workspace:listJobs – List processing jobs
  • workspace:saveJobMeta – Persist job metadata
  • workspace:deleteJob – Remove job record
  • workspace:library:list – List asset library
  • workspace:library:read – Read asset data
  • workspace:library:open – Open asset location

Workspace library handlers are registered via registerWorkspaceAssetLibraryIpcHandlers in electron/main/artifact-registry-service.ts.

IPC Communication Patterns

Modly uses three distinct communication patterns:

ipcRenderer.invoke / ipcMain.handle – Used for request-response operations where the renderer needs data or confirmation. Returns a Promise that resolves with the handler's return value. Used by fs:selectImage, model:download, and system:memory.

ipcRenderer.send / ipcMain.on – Used for fire-and-forget messages where no response is needed. Common for window controls like window:minimize and logging via log:error.

ipcRenderer.on / event.sender.send – Used for main-to-renderer events. The main process pushes data to the renderer using event.sender.send(channel, data), while the preload bridge sets up listeners via ipcRenderer.on. Used for progress updates (model:downloadProgress, extensions:installProgress) and backend notifications (python:log).

Practical Usage Examples

Controlling Window State

// Minimize the application window
window.electron.window.minimize();

// Check if window is maximized
const isMaximized = await window.electron.window.isMaximized();

// Listen for maximize state changes
window.electron.window.onMaximizeChange((isMax) => {
  console.log(`Window maximized: ${isMax}`);
});

Selecting Files and Directories

// Open image picker dialog
const imagePath = await window.electron.fs.selectImage();

// Select directory with default path
const dirPath = await window.electron.fs.selectDirectory('/home/user/projects');

// Read file as base64 for preview
const base64Data = await window.electron.fs.readFileBase64('/path/to/model.obj');

Managing Model Downloads with Progress

// Start downloading a model
await window.electron.model.download('stable-diffusion-xl');

// Listen for progress updates
window.electron.model.onProgress((data) => {
  console.log(`Downloaded ${data.percent}% of ${data.modelId}`);
});

// Pause an active download
await window.electron.model.pauseDownload('stable-diffusion-xl');

Installing Extensions

// List installed extensions
const extensions = await window.electron.extensions.list();

// Install from GitHub with progress tracking
const result = await window.electron.extensions.installFromGitHub(
  'https://github.com/username/extension-repo'
);

// Listen to installation progress
window.electron.extensions.onInstallProgress((progress) => {
  console.log(`Installation: ${progress.stage} - ${progress.percent}%`);
});

Querying System Resources

// Get memory statistics
const mem = await window.electron.system.memory();
console.log(`Available: ${mem.available}MB / Total: ${mem.total}MB`);

Summary

  • Modly uses a typed preload bridge defined in electron/preload/electron-api.ts that exposes window.electron to the React renderer, providing type-safe access to main process capabilities.
  • IPC channels follow a domain:action naming convention, with domains including window, fs, model, extensions, python, system, and workspace.
  • Three communication patterns are implemented: invoke/handle for request-response, send/on for fire-and-forget, and event.sender.send/ipcRenderer.on for main-to-renderer events.
  • File system operations use invoke exclusively to return paths and file contents asynchronously.
  • Progress tracking relies on main-to-renderer events for real-time updates during long-running operations like model downloads and extension installations.
  • Python backend integration uses bidirectional IPC to manage subprocess lifecycle and stream logs to the UI.

Frequently Asked Questions

How does Modly secure IPC communications between renderer and main process?

Modly implements context isolation by using a preload script (electron/preload/index.ts) that explicitly exposes only necessary APIs via contextBridge.exposeInMainWorld. The electron-api.ts file defines a typed interface that restricts renderer access to specific whitelisted channels, preventing arbitrary IPC calls and following Electron security best practices.

Can I add custom IPC channels to Modly?

Yes. To add a new channel, define the method in electron/preload/electron-api.ts using ipcRenderer.invoke, send, or on, then register the corresponding handler in electron/main/ipc-handlers.ts using ipcMain.handle or ipcMain.on. Ensure channel names follow the existing domain:action convention and update the TypeScript interfaces to maintain type safety across the bridge.

Why do some channels use invoke while others use send?

invoke is used when the renderer requires a response or confirmation from the main process, such as retrieving file paths (fs:selectImage) or checking system memory (system:memory). send is used for fire-and-forget operations where no return value is needed, such as window minimization (window:minimize) or logging errors (log:error). Event channels like model:downloadProgress use ipcRenderer.on to receive push notifications from the main process.

Where are the IPC handlers for workspace library operations defined?

While most IPC handlers reside in electron/main/ipc-handlers.ts, the workspace library-specific channels (workspace:library:list, workspace:library:read, workspace:library:open) are registered through the registerWorkspaceAssetLibraryIpcHandlers function in electron/main/artifact-registry-service.ts, demonstrating how Modly modularizes IPC registration across different service files.

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 →