Native UI from JSX + CSS

Write web code. Ship nativeapps.

Morph compiles .mx files into lightweight native binaries with OpenGL rendering. No browser. No Electron. Under 1 MB.

Get Started
$pip install levizr-morph
App.mx
import { morphState } from 'morph'
export default function App() {
const [count, setCount] = morphState(0);
return (
<body>
<div className="app">
<div className="title">Hello, {count}!</div>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
</body>
);
}
<0 MB
Binary size
0
Runtime deps
0+
Tailwind utils
0.0
OpenGL core
Why Morph

Everything you love about the web.
Everything you need for native.

Native Binaries

Compile to standalone native binaries under 1 MB. No browser runtime, no Electron, no WebView — just raw OpenGL.

Full CSS + Tailwind

Write styles with standard CSS or 500+ Tailwind utilities. Flexbox, animations, transforms, transitions — all supported.

Instant Hot Reload

Dev mode watches your files, recompiles only the logic, and hot-swaps it via dlopen. Window never restarts.

JSX + TypeScript

Build UIs with familiar JSX syntax and TypeScript logic. Your JS is translated to C++ at compile time.

C++ Interop

Import C++ functions directly into your JSX. Full access to native libraries with zero-cost FFI.

Dead Code Elimination

Feature-based tree-shaking at compile time. Only link what you use — text, flex, animation, transforms.

Under the Hood

From JSX to native.
No runtime required.

.mx Files

JSX + TypeScript + CSS

Parse

Tree-sitter AST

Style

CSS + Tailwind resolve

Layout

Box model + Flexbox

Codegen

C++ via Jinja2

Binary

Native OpenGL app

Dev Mode

File changes trigger incremental recompilation. The IR is sent over a Unix socket to a pre-compiled dev runtime. Only the logic shared library is recompiled and hot-swapped via dlopen — signals and effects are re-wired in place.

morph dev

Build Mode

Full compilation to a standalone native binary. TypeScript is translated to C++ via tree-sitter. Jinja2 templates emit optimized C++ code with feature-based dead code elimination. Optional UPX compression.

morph build --static --upx
Code Examples

Familiar syntax.
Native power.

import { CSS, morphState } from 'morph'
CSS.load("style.css")
export const windowConfig = {
title: "Counter",
width: 400,
height: 300,
}
export default function App() {
const [count, setCount] = morphState(0);
return (
<body>
<div className="counter">
<div className="count">{count}</div>
<div className="actions">
<button
className="btn btn-primary"
onClick={() => setCount(count + 1)}
>
+1
</button>
<button
className="btn btn-secondary"
onClick={() => setCount(0)}
>
Reset
</button>
</div>
</div>
</body>
);
}
CLI

One CLI to rule them all.

From scaffolding to production builds, everything you need is one command away.

Terminal
$morph init my-app
$morph dev
$morph build
$morph run
$morph build --static --upx
$morph doctor
$morph translate src/logic.ts

Ready to go native?

Install Morph, scaffold a project, and build your first native app in under a minute.

$pip install levizr-morph
View on GitHub