GitHub

Mystral Native.js

Discord Release MIT License

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 | bash

Windows (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

Note

Linux prebuilt binaries work with X11, but not with Wayland. Wayland is supported if you clone and build yourself (see "Build from Source" below). Currently tracking in Issue 18.

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 (x64) mystral-linux-x64-v8-dawn.zip
Linux (ARM64) mystral-linux-arm64-quickjs-wgpu.zip
unzip mystral-macOS-arm64-v8-dawn.zip
cd mystral-macOS-arm64-v8-dawn
./mystral run examples/triangle.js

Option 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

Read the original on github.com ↗