Murasaki

Architecture

How the Rust host, local Node runtime, and WebView renderer fit together.

Murasaki is a three-layer desktop runtime. React renders in the operating system WebView, application backend code runs in a bundled Node.js process, and a small Rust host owns the native window and application lifecycle.

┌──────────────── Native application ────────────────┐
│                                                    │
│  Rust host (tao / wry / muda)                      │
│  windows · WebViews · native menus · update handoff│
│                       │                            │
│                       │ launches / supervises      │
│                       ▼                            │
│  Local Node runtime                                │
│  src/main.ts · use-main · use-server · API routes  │
│                       │                            │
│                       │ authenticated loopback HTTP│
│                       ▼                            │
│  OS WebView                                        │
│  React 19 · Murasaki router · your renderer code   │
│                                                    │
└────────────────────────────────────────────────────┘

This is deliberately different from Electron's embedded Chromium + Node renderer model. Renderer code does not receive Node globals. Put filesystem, database, socket, worker, and secret-bearing code in src/main.ts, a 'use main' module, a 'use server' action, or an src/api/ route.

Layer responsibilities

LayerOwnsDoes not own
Rust hostNative event loop, declared application windows, per-window navigation/capability policy, OS open-request normalization, menus, Node child supervision, final update handoffBusiness logic and React state
Local Node runtimeLong-lived main lifecycle, registered URL/file handling, actions, API routes, update verification, application resources and dataArbitrary native window creation
RendererUI, routing, browser APIs, typed backend calls, permitted management of declared windowsDirect filesystem/Node/native module access

Murasaki is pre-1.0. Declared windows have independent, deny-by-default command allowlists, but capability arguments and path/URL scopes are not yet policy-controlled. Packaged macOS/Windows apps enforce a single instance, can register URL schemes and file associations, and expose matching activations to Node Main through openRequested(). Check Platform & feature status before committing a production architecture to a feature.

Development and packaged runtime

The application code keeps the same boundaries in both modes, but the host processes differ:

murasaki devPackaged app
Web assetsVite dev server with HMRdist/client served by bundled Node
Node backendVite child processPortable Node runtime inside app resources
Native hostCLI process loads @murasakijs/nativeStandalone Rust launcher
Declared windowsAll routes created with individual dev WebViewsAll routes created from resolved bundle metadata
Main entryLoaded with Vite SSR; exact entry hot-reloadsCompiled to server/main.mjs
Backend callsVite middlewareBundled loopback HTTP server
URL/file registrationNot installed by dev modemacOS app metadata or Windows installer registry

Production uses a deterministic loopback port derived from appId, giving the renderer a stable origin across launches. The Windows WebView2 profile is also isolated by appId. Keep appId stable after release: changing it can change the application data paths, browser profile, bundle identity, single-instance lock, and local origin.

Next.js-like, not Next.js itself

Murasaki adopts familiar conventions—src/app, layouts, route handlers, directives, and React 19—but it is not the Next.js runtime. There are no React Server Components or Edge runtime, and middleware only participates in client navigation. Each guide documents the supported subset; do not assume an API is available because it exists in Next.js.

Next

On this page