Defold × TypeScript × Hermes

Make games. Stay typed.

Write Defold games in TypeScript with generated engine APIs, a fast local development loop, Hermes on native targets, and the browser's JavaScript engine on HTML5.

pnpm dlx @ts-defold/deherm create my-game --name "My Game"
cd my-game
pnpm install
pnpm dev
Quick start

Playable in four commands.

Scaffold a complete Defold + TypeScript game, or add déherm to the directory that already contains your game.project. The project’s selected Defold revision remains the source of truth.

New game
pnpm dlx @ts-defold/deherm create my-game --name "My Game"
cd my-game
pnpm install
pnpm dev
Existing Defold game
cd my-defold-game
pnpm add -D @ts-defold/deherm
pnpm exec deherm generate
pnpm exec deherm dev
01 · Author

Save this as src/player.script.ts. Generation creates the /src/player.script proxy that you attach to a game object in Defold.

02 · Play

pnpm dev opens the full TUI. Press p to build and launch native Defold; press w for HTML5.

03 · Iterate

Save TypeScript or an asset. The watcher compiles the new generation, activates it, and reports HMR and runtime telemetry in the same console.

src/player.script.tsgenerated as /src/player.script
import { defold, defineComponent, go, property, vmath } from "@deherm/project";

interface Player {
  speed: number;
}

export default defineComponent({
  properties: {
    speed: property.number(180),
  },

  init(): void {
    defold.log("info", "TypeScript is running in Defold");
  },

  update(self: Player, dt: number): void {
    const position = go.getPosition();
    go.setPosition(vmath.vector3(position.x + self.speed * dt, position.y, position.z));
  },
});
The loop

Built for the work between saves.

The editor and terminal are one development surface: generation state, engine targets, logs, live instances, source maps, profiles, and hot reload stay visible.

TUI

Build, launch, inspect, reload.

The default CLI is a full terminal UI. It follows the current generation into native Defold and HTML5, reports the exact activated bundle fingerprint, exposes live logs and target telemetry, and keeps controls discoverable on laptop keyboards.

file watcherincremental compilernative + HTML5HMR statuslive logsprofiles
Déherm development TUI showing build state, targets, logs, and metrics
VS Code

Your game, alive in the editor.

The language server understands generated Defold resources and component contexts. The extension adds inline property defaults, live instance values, TypeScript source-mapped debugging, evaluate, CPU profiles, and streaming heap snapshots.

completion + hoverresource namesbreakpointslive instances.cpuprofile.heapsnapshot
VS Code editing a Defold TypeScript component with live values
Measured in Release

Know what the boundary costs.

Every headline uses nanoseconds. These generated transport measurements isolate crossing and framing work over stub providers so engine work cannot hide it.

Direct generated C ABI

3.8 ns

1.0× fastest direct ABI. Fastest observed borrowed-handle frame; the measured range was 3.8–5.9 ns.

Static Hermes typed-native

64.6 ns

17.0× fastest direct ABI. Median across 19 argument/result shapes; 40.0–695.5 ns observed.

Complete generated Lua crossing

283.2 ns

74.5× fastest direct ABI. Protected Lua alone measured 211.0 ns; déherm added 70.9 ns of staging and transport.

Release host harness over stub providers. This measures generated crossing/framing cost, not the Defold call behind it; the Lua harness uses pinned PUC Lua 5.1 rather than Defold's shipping LuaJIT. Host: Apple M4, 20,000 warm-up calls, best of 9 × 100,000 calls.

arm64 macOS release
16.0 MiB

Complete War Battles .app logical file bytes.

Linked déherm engine
15.6 MiB
Stock Defold release engine
6.72 MiB
Hermes + déherm engine delta
+8.89 MiB (132%)
Optimized game bytecode
332.0 KiB
HTML5 / wasm-web release
4.26 MiB

Complete deployable browser directory. The browser lane does not embed Hermes.

Wasm engine
3.20 MiB
Engine JavaScript
712.1 KiB
Déherm browser-host delta
+870.5 KiB (28%)
Hermes embedded
no

Logical file-byte totals from fresh Bob release bundles. Native overhead compares the linked arm64-macOS executable to Bob's stock dmengine_release from the same pinned Bob jar. Browser overhead compares the Wasm and JavaScript engine shell to stock wasm-web release members; HTML5 embeds no Hermes. Signing, compression by a store/CDN, filesystem allocation, and platform packaging outside these bundle directories are excluded.

One authored surface

The runtime follows the target.

The generator emits the whole compatible API once. The build keeps only reachable code and selects the transport that belongs on the target.

◆

Native development

Dynamic Hermes keeps iteration immediate: bundle JavaScript to Hermes bytecode, load it in the Defold extension, and hot reload without relinking the engine.

Hermes bytecode + JSI
▲

Native release

Static Hermes can compile the reachable typed subset through generated C ABI bindings. Dynamic Hermes remains available where the selected profile needs it.

typed-native + generated fallback
●

HTML5

Use the JavaScript engine already in the browser. Generated direct-memory bindings call into Defold’s Wasm engine without embedding another VM or using embind.

browser JS + Wasm direct memory
Native module directory

Portable capability, with receipts.

This is the smaller, déherm-specific directory: headless or mixed native capabilities whose Defold targets and evidence are recorded. Use deherm module report <package> --directory to inspect an installed Expo, Turbo, Nitro, JSI, or Defold module and enrich the report from React Native Directory. Ecosystem declarations nominate candidates; only déherm compile and runtime records earn those labels here.

headless

Defold WebTransport

Source ↗

WebTransport-shaped Defold extension with Lua, C, dynamic Hermes/JSI, Static Hermes, and browser backends.

10 generation-supported2 runtime-verified
Target evidence
Defold targetStatusEvidence
arm64_sim-iosgeneration-supportedgeneration
arm64-androidgeneration-supportedgeneration
arm64-iosgeneration-supportedgeneration
arm64-linuxgeneration-supportedgeneration
arm64-osxruntime-verifiedruntime ↗
armv7-androidgeneration-supportedgeneration
wasm_pthread-webgeneration-supportedgeneration
wasm-webruntime-verifiedruntime ↗
x86_64-androidgeneration-supportedgeneration
x86_64-linuxgeneration-supportedgeneration
x86_64-osxgeneration-supportedgeneration
x86_64-win32generation-supportedgeneration
deherm module list
Ship something

Examples that exercise the product.

Start small, then inspect the dogfood game and the standalone networking extension when you need the full stack.

War Battles Online

A complete Defold game written in TypeScript: generated components, GUI, native and browser targets, hot reload, Static Hermes reachability, bots, and a 32-player network simulation.

Explore the game →

WebTransport

A separately usable Defold extension with a Lua API, C API, TypeScript surface, browser backend, native QUIC backend, and minimal Deno echo server.

Use the extension →