Fetching documentation…
Build native desktop applications with HTML, CSS, and JavaScript. No browser, no Electron, no WebView — just a lightweight native binary.
morph new my-app
cd my-app
morph devWrite familiar .mx files (JSX + CSS + TypeScript). Morph compiles them directly to native OpenGL binaries with zero runtime overhead.
// src/App.mx
import { morphState } from 'morph'
import "./style.css"
export const windowConfig = { title: "My App", width: 800, height: 600 }
export default function App() {
const [count, setCount] = morphState(0)
return (
<body>
<div className="app">
<h1 style="color: #e0e0e0;">Hello from Morph</h1>
<button className="btn" onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
</div>
</body>
)
}morph dev # live window, hot reload
morph run # optimized native binary| Electron | Qt | Morph | |
|---|---|---|---|
| Write UI in | HTML/CSS/JS | C++ / QML | TS/JSX/CSS |
| Runtime | Chromium (~150MB) | Qt libs | Zero |
| Binary size | ~80MB+ | ~20MB+ | 162KB* |
| Native OpenGL | ✗ | ✓ | ✓ |
| Hot reload | ✓ | ✗ | ✓ |
* Self-contained hello-world; a full app with routing, windows, state and native code is still ~330KB. Measured, not estimated — see App disk size: benchmarks.
Your hello-world — renderer, layout, fonts — in 162KB, zero dependencies. A kitchen-sink app with routing, windows, reactive state and native code still ships around 330KB. For perspective:
| What | Size | Can it render your UI? |
|---|---|---|
| Morph hello-world | 162KB | ✅ yes, all of it |
| Tauri hello-world | ~1.5MB | ✅ (needs your OS webview) |
| Flutter hello-world | ~13.5MB | ✅ |
| One 1080p stock photo | ~300KB | ❌ it's a picture of a dog |
| Electron hello-world | ~95MB | ✅ (586× bigger. It ships a whole browser. For "hello".) |
Dial-up could download your Morph app before the modem finished its scream. An Electron "hello world" needs a loading bar.
.mx files — JSX-like syntax with TypeScript/JavaScript and CSS in a single filemorphState and morphEffect for component reactivityfetch() with coroutines, runs on worker threads.cpp files directly into your JSXmorph.config.json options