Mystral Native.js
Run JavaScript/TypeScript games natively with WebGPU. Mystral Native.js is a lightweight runtime that lets you write games using familiar Web APIs (WebGPU, Canvas, Audio, fetch) and run them as native desktop applications on macOS, Windows, and Linux.
Think of it as "Electron for games" but without Chromium — just your game code, a JS engine, and native WebGPU rendering.
Note
Mystral Native.js is in early alpha. The core features work — execute JS against WebGPU, Canvas 2D, Web Audio, and fetch — with runtimes available for macOS, Windows, and Linux. Embedding is available for iOS and Android, with a future goal of console support. To see a production build, check out the Sponza demo on itch.io.
Quick Start
Option 1: Install via CLI (Recommended)
macOS / Linux:
curl -fsSL https://mystralengine.github.io/mystralnative/install.sh | bashWindows (PowerShell):
irm https://mystralengine.github.io/mystralnative/install.ps1 | iex
This detects your platform, downloads the latest release, installs to ~/.mystral/ (or $HOME\.mystral\ on Windows), and adds mystral to your PATH. Then run the examples:
# macOS / Linux cd ~/.mystral mystral run examples/triangle.js mystral run examples/mystral-helmet.js # GLTF loading demo
# Windows (PowerShell) cd $HOME\.mystral mystral run examples\triangle.js mystral run examples\mystral-helmet.js # GLTF loading demo
Option 2: Download Prebuilt Binary
Download the latest release for your platform from the releases page:
| Platform | Download |
|---|---|
| macOS (Apple Silicon) | mystral-macOS-arm64-v8-dawn.zip |
| macOS (Intel) | mystral-macOS-x64-v8-dawn.zip |
| Windows | mystral-windows-x64-v8-dawn.zip |
| Linux | mystral-linux-x64-v8-dawn.zip |
unzip mystral-macOS-arm64-v8-dawn.zip
cd mystral-macOS-arm64-v8-dawn
./mystral run examples/triangle.jsOption 3: Build from Source
git clone https://github.com/mystralengine/mystralnative.git cd mystralnative # Install bun if you don't have it curl -fsSL https://bun.sh/install | bash # Download dependencies bun install bun run deps:download # Configure with V8 + Dawn (recommended) cmake -B build \ -DMYSTRAL_USE_V8=ON \ -DMYSTRAL_USE_DAWN=ON \ -DMYSTRAL_USE_QUICKJS=OFF \ -DMYSTRAL_USE_WGPU=OFF # Build cmake --build build --parallel # Run an example ./build/mystral run examples/triangle.js
What Can You Build?
Here's a complete "Hello Triangle" — the traditional first GPU program:
// hello-triangle.js const adapter = await navigator.gpu.requestAdapter(); const device = await adapter.requestDevice(); const context = canvas.getContext("webgpu"); const format = navigator.gpu.getPreferredCanvasFormat(); context.configure({ device, format }); const shader = device.createShaderModule({ code: ` @vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f { var pos = array<vec2f, 3>( vec2f( 0.0, 0.5), vec2f(-0.5, -0.5), vec2f( 0.5, -0.5) ); return vec4f(pos[i], 0.0, 1.0); } @fragment fn fs() -> @location(0) vec4f { return vec4f(1.0, 0.5, 0.2, 1.0); // orange } `, }); const pipeline = device.createRenderPipeline({ layout: "auto", vertex: { module: shader, entryPoint: "vs" }, fragment: { module: shader, entryPoint: "fs", targets: [{ format }] }, }); function render() { const encoder = device.createCommandEncoder(); const pass = encoder.beginRenderPass({ colorAttachments: [{ view: context.getCurrentTexture().createView(), clearValue: { r: 0.1, g: 0.1, b: 0.1, a: 1 }, loadOp: "clear", storeOp: "store", }], }); pass.setPipeline(pipeline); pass.draw(3); pass.end(); device.queue.submit([encoder.finish()]); requestAnimationFrame(render); } render();
Save it and run:
mystral run hello-triangle.js
You'll see an orange triangle on a dark background — rendered natively via WebGPU with no browser involved.
Running Examples
# Basic WebGPU triangle mystral run examples/triangle.js # 3D rotating cube mystral run examples/simple-cube.js # Full 3D scene with PBR lighting (Dawn builds only) mystral run examples/mystral-helmet.js # Day/night cycle demo with atmosphere mystral run examples/daynight.js # Sponza palace with day/night, torches, fireflies (Dawn builds only) mystral run examples/sponza.js # Three.js WebGPU (requires bundling, see docs site for full guide) npm install three@0.182.0 npx esbuild examples/threejs-cube-src.js --bundle --outfile=threejs-bundle.js --format=esm --platform=browser mystral run threejs-bundle.js # PixiJS v8 WebGPU (requires bundling, WebGPU renderer only) npm install pixi.js@^8.0.0 npx esbuild examples/pixijs-sprite-src.js --bundle --outfile=pixijs-bundle.js --format=esm --platform=browser mystral run pixijs-bundle.js # Custom window size mystral run examples/simple-cube.js --width 1920 --height 1080 # Watch mode — auto-reload on file changes mystral run game.js --watch # Headless screenshot (for CI/testing) mystral run examples/simple-cube.js --headless --screenshot output.png
Example Files
| Example | Description |
|---|---|
triangle.js |
Minimal WebGPU — orange triangle |
simple-cube.js |
3D cube with matrices |
test-audio.js |
Web Audio API test |
test-gamepad.js |
Gamepad API test |
mystral-helmet.js |
Full Mystral Engine with DamagedHelmet model |
daynight.js |
Day/night cycle with atmosphere, stars, moon, torches |
sponza.js |
Sponza palace with day/night cycle, torches, fireflies |
threejs-cube-src.js |
Three.js WebGPU example (requires bundling) |
pixijs-sprite-src.js |
PixiJS v8 WebGPU example (requires bundling) |
Bundling for Distribution
Package your game into a single executable that players can run with no dependencies:
# Compile into a standalone binary (Linux/Windows) mystral compile game.js --include assets --out dist/my-game ./dist/my-game # Create a standalone .bundle for macOS .app packaging mystral compile game.js --include assets --bundle-only --out dist/game.bundle
See the distribution guide for platform-specific packaging details including macOS .app bundles, code signing, and more.
Production Builds
Use the production build script to create stripped, optimized, asset-filtered builds locally (mirrors CI):
# Full production build of Sponza demo (strips binary, filters assets, creates .app + .zip) ./scripts/build-production.sh # Build a different demo ./scripts/build-production.sh --demo helmet # Skip cmake rebuild (repackage with existing binary) ./scripts/build-production.sh --skip-build
CLI Reference
mystral run <script.js> [options] Run a JavaScript/TypeScript file
mystral compile <entry.js> [options] Bundle into single executable
mystral --version Show version
mystral --help Show help
Run Options:
--width <n> Window width (default: 1280)
--height <n> Window height (default: 720)
--title <str> Window title
--headless Run with hidden window
--watch, -w Auto-reload on file changes
--screenshot <file> Take screenshot and quit
--frames <n> Frames before screenshot (default: 60)
--quiet, -q Suppress output except errors
Compile Options:
--include <dir> Asset directory to bundle (repeatable)
--output, -o <file> Output path
--bundle-only Create .bundle file (for .app packaging)
--root <dir> Root directory for bundle paths (default: cwd)
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Your Game (JS/TS) │
│ Uses WebGPU, Canvas, Audio APIs │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ MystralNative Runtime │
│ WebGPU Bindings │ Canvas 2D │ Audio │ fetch │ Input │
└─────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌───────────┐ ┌─────┐ ┌──────┐ ┌───────┐
│ V8/JSC/ │ │ Dawn/ │ │SDL3 │ │libcurl│ │ libuv │
│ QuickJS │ │ wgpu-native│ │ │ │ │ │ │
└─────────┘ └───────────┘ └─────┘ └──────┘ └───────┘
Supported APIs
| API | Status |
|---|---|
| WebGPU | ✅ Full support |
| Canvas 2D (Skia) | ✅ Working |
| Web Audio | ✅ Working |
| fetch (file/http/https) | ✅ Working |
| URL / URLSearchParams | ✅ Working |
| Worker (main-thread) | ✅ Working |
| Gamepad | ✅ Working |
| requestAnimationFrame | ✅ Working |
| setTimeout/setInterval | ✅ Working |
| ES Modules (import/export) | ✅ Working |
| TypeScript (via SWC) | ✅ Working |
| GLTF/GLB loading (incl. Draco) | ✅ Working |
Platform Support
| Platform | JS Engine Options | WebGPU Backend |
|---|---|---|
| macOS (arm64) | V8, JSC, QuickJS | Dawn, wgpu-native |
| macOS (x64) | V8, JSC, QuickJS | Dawn, wgpu-native |
| Windows | V8, QuickJS | Dawn, wgpu-native |
| Linux | V8, QuickJS | Dawn, wgpu-native |
| iOS | JSC, QuickJS | wgpu-native |
| Android | V8, QuickJS | wgpu-native |
Build Options
Recommended for development (full shader compatibility):
cmake -B build \ -DMYSTRAL_USE_V8=ON \ -DMYSTRAL_USE_DAWN=ON \ -DMYSTRAL_USE_QUICKJS=OFF \ -DMYSTRAL_USE_WGPU=OFF
Alternative configurations:
Choose your JS engine:
cmake -B build -DMYSTRAL_USE_V8=ON # Recommended — Full V8 with JIT cmake -B build -DMYSTRAL_USE_QUICKJS=ON # Smallest binary, good for CI cmake -B build -DMYSTRAL_USE_JSC=ON # macOS/iOS system engine
Choose your WebGPU backend:
cmake -B build -DMYSTRAL_USE_DAWN=ON # Recommended — Chrome's implementation cmake -B build -DMYSTRAL_USE_WGPU=ON # Rust implementation, best iOS/Android support
Embedding in Your App
Use MystralNative as a library in your C++ application:
#include "mystral/runtime.h" int main() { mystral::RuntimeConfig config; config.width = 1280; config.height = 720; config.title = "My Game"; auto runtime = mystral::Runtime::create(config); runtime->loadScript("game.js"); runtime->run(); return 0; }
See the embedding guide for iOS, Android, and CMake integration details.
Dependencies
All dependencies are downloaded automatically as prebuilt binaries:
| Dependency | Purpose |
|---|---|
| Dawn / wgpu-native | WebGPU implementation |
| SDL3 | Windowing, input, audio |
| V8 / QuickJS / JSC | JavaScript engine |
| Skia | Canvas 2D rendering |
| libcurl | HTTP requests |
| libuv | Async I/O, timers, file watching |
| Draco | Native Draco mesh decompression (optional) |
| SWC | TypeScript transpiling |
Prebuilt dependency binaries are managed via mystralengine/library-builder.
Documentation
Full documentation is available at mystralengine.github.io/mystralnative.
- Three.js WebGPU Guide - Using Three.js with MystralNative
- PixiJS v8 WebGPU Guide - Using PixiJS v8 with MystralNative (WebGPU renderer only)
- CLI Reference - Command line options
- Building from Source - Build configuration options
Contributing
Issues and PRs welcome! See the GitHub repository.
License
MIT License — see LICENSE for details.
