How to Start the Desktop Development Environment with HMR in Apache Maka

Run npm run dev from the repository root to launch the Maka Desktop environment with Hot Module Replacement (HMR), triggering incremental builds, a Vite dev server, and an Electron instance that reloads instantly on code changes.

The Apache Maka desktop application is a multi-workspace TypeScript project built on Electron. Starting the Desktop development environment with HMR in Maka relies on a single orchestration script that coordinates esbuild, TypeScript incremental compilation, and Vite's React HMR to deliver sub-second feedback loops.

The Entry Command

The development workflow begins at the repository root. The package.json defines a dev script on line 44 that delegates to the desktop workspace:

"dev": "npm --workspace @maka/desktop run dev:hmr --"

Executing npm run dev forwards execution to apps/desktop, where the dev:hmr script invokes node scripts/dev.mjs. This is the only command required to bootstrap the entire HMR pipeline.

The Build Pipeline Architecture

The apps/desktop/scripts/dev.mjs script orchestrates a complex build graph to ensure the main process, preload scripts, and renderer are ready before Electron opens.

Parallel Workspace Compilation

First, the script initiates incremental compilation for shared libraries using the TypeScript build API:

tsc --build tsconfig.lib.json

This generates a shared .tsbuildinfo file, enabling fast rebuilds that skip unchanged files. Simultaneously, esbuild bundles three distinct targets in parallel:

  • Filesystem-worker – Background file system operations
  • Preload – The context bridge defined in src/preload/preload.ts
  • Cursor-overlay – Independent esbuild task for overlay UI components

Main Process Bundling

Once the shared libraries stabilize, dev.mjs bundles the Electron main process entry point at src/main/main.ts via esbuild. This must complete before the renderer initializes to ensure the main process can successfully load the preload script.

Vite HMR for the Renderer

While esbuild handles the Node.js side, the renderer process uses a Vite dev server for native ES module HMR.

Dev Server Configuration

The apps/desktop/vite.config.ts configures the server with the React plugin and sets base: "./" to support Electron's file protocol. When createServer() executes, it serves src/renderer assets on a local port (default 5173).

Renderer Warm-up Strategy

Before spawning Electron, the script issues a warmup request targeting /main.tsx and waits for the dependency crawl to settle via waitForRequestsIdle. This step is critical: it ensures the Vite optimizer has committed the full import graph, preventing the "two React instances" runtime crash documented in the comments (lines 66-71 of dev.mjs). The warmup guarantees all dependencies are pre-bundled and deduplicated before the Electron window connects.

Launching Electron

With the renderer primed, the startDevelopmentApp function in apps/desktop/scripts/dev-app-runtime.mjs spawns Electron pointing at the Vite URL:

http://localhost:5173/

The renderer connects to this endpoint and establishes a WebSocket link for HMR updates. Any modifications to apps/desktop/src/renderer/**/*.tsx (or imported workspace packages) trigger Vite's module invalidation and push updates instantly to the running window without reloading the full Electron process.

macOS-Specific Configuration

On macOS, you can opt into a signed developer bundle to persist Accessibility and Screen Recording permissions (TCC) across launches:

MAKA_DEV_TCC=1 npm run dev

Without this flag, the script launches a plain Electron binary, which requires re-granting permissions on every restart.

Expected Terminal Output

A successful startup sequence produces the following log pattern:

[build] model metadata — generating from committed snapshot
[build] libraries — starting (tsc --build)
[build] libraries (all) — done
[build] preload — done
[build] cursor overlay — done
[build] main — starting
[build] main — done
[vite] starting dev server...
> Local: http://localhost:5173/
[vite] warming renderer entry and waiting for the dep crawl to settle...
[electron] launching against http://localhost:5173/ (renderer HMR live)

Once [electron] launching appears, the desktop window is live and accepts HMR updates.

Summary

  • Execute npm run dev from the repository root to start the complete HMR pipeline.
  • The script at apps/desktop/scripts/dev.mjs coordinates parallel TypeScript (tsc) and esbuild tasks for the main process, preload, and workers.
  • A Vite dev server serves the renderer with React Fast Refresh enabled via apps/desktop/vite.config.ts.
  • A warmup request to /main.tsx prevents duplicate React instances by forcing Vite to finish dependency optimization before Electron launches.
  • Use MAKA_DEV_TCC=1 on macOS to retain system permissions through signed bundle launches.

Frequently Asked Questions

What triggers HMR updates in the Maka Desktop environment?

Any file change under apps/desktop/src/renderer/ or within dependent workspace packages triggers Vite's file watcher. The dev server invalidates affected modules and pushes updates via WebSocket to the Electron renderer, updating the UI without restarting the application.

Why does the dev script wait for a dependency crawl to complete?

The waitForRequestsIdle call in dev.mjs ensures Vite's optimizer has fully resolved and de-duplicated the import graph (including React). Without this guard, Electron could load renderer code before optimization finishes, leading to conflicting React instances and runtime crashes.

Can I run the desktop dev script without using npm run dev?

Yes. Navigate to apps/desktop and run node scripts/dev.mjs directly. This bypasses the root workspace delegation but executes the identical pipeline. Ensure all workspace dependencies are built first, as the script assumes tsconfig.lib.json artifacts may already exist.

How do I preserve macOS TCC permissions during development?

Set the environment variable MAKA_DEV_TCC=1 when running the dev command. This instructs dev-app-runtime.mjs to use a signed development bundle, which retains Accessibility and Screen Recording grants between sessions instead of prompting on every launch.

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 →