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

> Start the Maka Desktop development environment with HMR by running npm run dev. Enjoy instant reloads and incremental builds with Vite and Electron for a faster workflow.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: getting-started
- Published: 2026-09-12

---

**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`](https://github.com/apache/maka/blob/main/package.json) defines a `dev` script on line 44 that delegates to the desktop workspace:

```json
"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:

```bash
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`](https://github.com/apache/maka/blob/main/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`](https://github.com/apache/maka/blob/main/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`](https://github.com/apache/maka/blob/main/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`](https://github.com/apache/maka/blob/main//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:

```bash
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:

```bash
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:

```text
[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`](https://github.com/apache/maka/blob/main/apps/desktop/vite.config.ts)**.
- A **warmup request** to [`/main.tsx`](https://github.com/apache/maka/blob/main//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`](https://github.com/apache/maka/blob/main/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.