Skip to main content

Build native OpenGL Applications with HTML, CSS, and JavaScript

Project description


███╗   ███╗ ██████╗ ██████╗ ██████╗ ██╗  ██╗
████╗ █████║██╔═══██╗██╔══██╗██╔══██╗██║  ██║
██╔████╔██║██║   ██║██████╔╝██████╔╝███████║
██║╚██╔╝██║██║   ██║██╔══██╗██╔═══╝ ██╔══██║
██║ ╚═╝ ██║╚██████╔╝██║  ██║██║     ██║  ██║
╚═╝     ╚═╝ ╚═════╝ ╚═╝  ╚═╝╚═╝     ╚═╝  ╚═╝

Build native OpenGL Applications with HTML, CSS, and JavaScript.

No browser. No Electron. No WebView. Just a lightweight native binary.


License Python C++ OpenGL Status



What is Morph?

Morph is a UI framework that compiles .mx files (JSX-like syntax with CSS and JavaScript) directly into native OpenGL binaries. You write familiar web syntax — Morph produces a lean, native binary with zero browser overhead.

<!-- src/App.mx -->
<morph-window title="My App" width="800" height="600">
  <div style="height: 48px; background: #1a1a2e;">
    <button morph-open="settings">Settings</button>
  </div>

  <h1 style="color: #e0e0e0;">Hello from Morph</h1>
</morph-window>
morph dev      # live window, hot reload via Unix socket
morph build    # optimized native binary

Why Morph?

Electron Qt Morph
Write UI in HTML/CSS/JS C++ / QML HTML/CSS/JS
Runtime Chromium (~150MB) Qt libs Zero
Binary size ~80MB+ ~20MB+ <1MB
Native OpenGL access
Hot reload
Custom C++ nodes

Quick Start

1. Install

pip install levizr-morph
morph doctor          # verify system dependencies

2. Create a project

morph init my-app
cd my-app

3. Start dev mode

morph dev

A native window opens. Edit src/App.mx — the window updates instantly without restarting.

4. Ship

morph build
# builds native binary

How It Works

Morph is a compiler, not an interpreter. Your source files never ship — only the compiled binary does.

src/App.mx ──► MorphParser ──► JSXWalker ──► IRBuilder ──► LayoutEngine ──► IR dict ──► C++ Codegen ──► g++ ──► native binary
                                                                                        │
                                                                                 [Dev: Unix Socket]

Python handles the entire toolchain — .mx parsing via tree-sitter, IR building, layout math, and Jinja2-based C++ code generation. C++ handles the runtime — OpenGL rendering, window management, and event handling. The final binary contains zero Python and zero Node.

In dev mode, the pipeline produces an IR dict that is sent over a Unix socket to a pre-compiled renderer (morph_devrt) on every file save. The window never closes — only the node tree swaps.


Current State (v0.0.5 — Early Development)

✅ Working

Component Status
.mx file parsing — tree-sitter-based JSX, imports, props Complete
CSS parsing — local files, remote URLs, MD5-cached Complete
Tailwind CSS — 500 common utility classes + arbitrary values Complete
IRBuilder — walked AST → IR with inline CSS, Tailwind, color/unit conversion Complete
CLIinit (interactive wizard), dev, build, pkg, doctor, cache Complete
Configmorph.config.json load/save Complete
IR data modelsIRNode, IRWindow, IRPage, IRViewport, IRStyle, IREvent Complete
IR serializer/deserializer — JSON-safe dict for dev socket Complete
Layout engine — box model (margin, padding), vertical stacking, gap, flexbox Complete
Dev file watcher — watchdog-based with debounce Complete
Unix socket IPC — sends IR to dev runtime Complete
C++ node emitter — IR → C++ instantiation code from Jinja2 templates Complete
Build compiler — g++ invocation with conditional FreeType/GLFW/OpenGL flags Complete
Package registry client — fetch, install, manifest parsing Complete
OpenGL 3.3 batch renderer — instanced VAO/VBO/IBO, uniform color + rounded rect SDF Complete
FreeType text rendering — per-size glyph atlas, batch text with kerning Complete
Rounded rectangles — SDF-based border-radius in fragment shader Complete
Font weight support — bold/normal font selection, font-weight CSS property Complete
Style inheritancecolor, font-size, font-weight, text-align cascade from parent Complete
Transparent backgrounds — only render when background-color set Complete
Event systemonClick, MouseDown, MouseUp, MouseMove events Complete
Scrollbar — browser-like drag, wheel, track-click, nested containers Complete
Viewport culling — skip off-screen children in draw + event dispatch Complete
Feature-based compilation#define MORPH_FEATURE_* guards, linker GC Complete
Flexboxjustify-content, align-items, two-pass layout, content-based sizing Complete
text-align — left, center, right with correct container-relative centering Complete
max-width — layout constraint for responsive sizing Complete
Margin/padding side propertiesmargin-top, padding-left, etc. Complete
Cursor supportcursor: pointer (hand), cursor: text (I-beam) Complete
morph_devrt binary — dev mode C++ renderer, Unix socket IPC, hot reload Complete
Border renderingborder-width, border-color, border-style with SDF shader on all elements (div, button, img); border ring batch on top of everything Complete
Image renderingstb_image-backed: PNG, JPEG, WebP, GIF, BMP, TGA, PSD, HDR, PNM, PIC; per-texture batching, border-radius clipping Complete
Box-sizingcontent-box and border-box CSS property Complete
Dev mode auto-build — CMake integration, automatic binary rebuild on missing Complete
Window config hot reload — title update on save, node tree swap without restart Complete
DevTools panel — F12 toggle, element inspect (F2/click), box-model overlay (margin/border/padding/content), element info panel Complete

🚧 In Progress

Component Status Notes
Style resolver — CSS cascade, specificity, selector matching Stub Only inline + Tailwind work via IRBuilder
JS interpreter — JS event handler → C++ lambdas Stub Only console.log works
Flexbox flex-wrap — row overflow wrapping Partial Content-based sizing works, wrap still in progress
position: relative/fixed — offset positioning, sticky Stub Not yet implemented

Features

CSS Properties (resolved from inline styles, CSS rules, and Tailwind classes)

  • width, height, max-width
  • margin, padding + individual side properties (margin-top, padding-left, etc.)
  • background-color, color (hex, rgb, named)
  • border-radius, border-width, border-color, border-style
  • box-sizingcontent-box, border-box
  • display: flex, flex-direction, justify-content, align-items, flex-wrap, gap
  • position, left, right, top, bottom
  • overflow, cursor
  • font-size (px, %, em, bare numbers), font-weight, text-align
  • color, font-size, font-weight, text-align cascade from parent to children

HTML Elements

  • div, span, h1h6, p, button
  • <img> — supports PNG, JPEG, WebP, GIF, BMP, TGA, PSD, HDR, PNM, PIC via stb_image; intrinsic aspect ratio; width/height attributes; border-radius clipping
  • <morph-window> — declares a native window

C++ Runtime

  • OpenGL 3.3 core profile batch renderer (instanced VAO/VBO/IBO)
  • Rounded rectangles via SDF fragment shader (radius auto-clamped)
  • Border rendering — border-width, border-color, border-style via SDF shader on all elements (div, button, img, etc.); border ring batch flushed on top of everything
  • box-sizing: content-box / border-box layout modes
  • FreeType text rendering with per-size glyph atlas and word-wrap
  • Font weight support (bold / normal with DejaVuSans-Bold.ttf)
  • Style inheritance cascade (color, font-size, font-weight, text-align)
  • Transparent backgrounds by default
  • onClick, MouseDown, MouseUp, MouseMove event dispatch
  • Scrollbar with drag, wheel, track-click; nested scroll containers
  • Viewport culling for draw + events
  • Feature-based dead code elimination
  • Image rendering — stb_image-backed texture loading (PNG/JPEG/WebP/GIF/BMP/TGA/PSD/HDR/PNM/PIC); per-texture-ID batched draw calls; border-radius stencil clipping on images
  • cursor: pointer and cursor: text via GLFW standard cursors

DevTools (morph_devrt only)

  • F12 — Toggle DevTools panel
  • F2 or click "Inspect Element" — Toggle inspect mode
  • Box-model overlay: margin (orange), border (yellow), padding (green), content (blue)
  • Element info panel: tag name, size, position, margin, padding, display, overflow, box-sizing, color (hex swatch), background (hex swatch), font size, font weight, text align
  • Hot reload preserves DevTools state

Project Structure

my-app/
├── src/
│   ├── App.mx            ← entry point (JSX + CSS + JS)
│   └── components/       ← reusable .mx components
├── cpp/                  ← optional custom C++ nodes
│   └── my_widget.h
├── assets/               ← fonts, textures, etc.
├── morph.config.json     ← project config + dependencies
└── dist/
    └── app               ← compiled binary (gitignored)

morph.config.json:

{
  "name": "my-app",
  "entry": "src/App.mx",
  "window": {
    "width": 1024,
    "height": 768,
    "title": "My App"
  },
  "dependencies": {},
  "cpp_sources": []
}

System Requirements

Linux macOS Windows
Python 3.10+ 3.10+ 3.10+
Compiler g++ 11+ clang++ 13+ MSVC / MinGW
OpenGL 3.3+ 3.3+ 3.3+
GLFW apt install libglfw3-dev brew install glfw bundled

Run morph doctor after installing to verify your environment.


Roadmap

v0.1.0 (Next Up)

  • CSS style resolver — Selector matching, cascade, specificity
  • JS interpreter — Full JS expression handling (CallExpression, BinaryExpression)
  • flex-wrap — Row overflow wrapping
  • position: relative / fixed — Offset and viewport-relative positioning
  • margin collapse — Collapsing vertical margins between siblings

Future

  • Multi-window & navigation system
  • <morph-viewport> embedded OpenGL canvas
  • Custom C++ node integration
  • morph-icons (first-party package)
  • morph-animate
  • Windows support
  • VSCode extension (syntax highlighting for .mx files)

Contributing

Morph is in early development. Contributions, ideas, and feedback are very welcome.

git clone https://github.com/levizr/morph
cd morph
pip install -e ".[dev]"
morph doctor

The most impactful areas right now are the CSS style resolver, morph_devrt binary, and JS interpreter. See the Current State section for a full breakdown.

Open an issue before starting on large features so we can align on design.


License

APACHE — see LICENSE.



Built with C++ and Python  ·  Rendered with OpenGL  ·  No browser required

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

levizr_morph-0.0.5.tar.gz (203.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

levizr_morph-0.0.5-py3-none-any.whl (232.0 kB view details)

Uploaded Python 3

File details

Details for the file levizr_morph-0.0.5.tar.gz.

File metadata

  • Download URL: levizr_morph-0.0.5.tar.gz
  • Upload date:
  • Size: 203.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for levizr_morph-0.0.5.tar.gz
Algorithm Hash digest
SHA256 a52aa6af99a3e1eeca506ea0364923900cebee3e02f86e0686430745623754f0
MD5 155991f33b8204a17bf9c8234b7ae429
BLAKE2b-256 52f130cb0626e49eeb23c79b5b3199274ce4ac44056798d8c0287090c00d7ada

See more details on using hashes here.

File details

Details for the file levizr_morph-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: levizr_morph-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 232.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for levizr_morph-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 4fd584596c4717b697079bee80d748acfa9ea853209ca45af46c41692b42dc90
MD5 b9949f377f0b6bf91be0dff67cfd8dac
BLAKE2b-256 558f0f10a3e9f629235b4bf1e40d509090ecb12c5e64de43c8822665c5929663

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page