You can ship a Lua game to Wavedash by running Lua 5.4 in the browser with wasmoon. No build step — wasmoon loads from a CDN at runtime, and you bind whatever JS objects your Lua code needs (window, document, Wavedash) as Lua globals.
For the Love2D engine specifically, see the dedicated Love2D guide. This page covers plain Lua runtimes.
Setup
Create a web/ folder with an index.html that bootstraps wasmoon and a main.lua with your game.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My Lua Game</title>
<style>
html, body { margin: 0; height: 100%; background: #111; }
#gameCanvas { width: 100%; height: 100%; display: block; }
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script type="module">
import { LuaFactory } from "https://cdn.jsdelivr.net/npm/wasmoon@1.16.0/+esm";
const factory = new LuaFactory();
const lua = await factory.createEngine();
const Wavedash = window.Wavedash;
lua.global.set("window", window);
lua.global.set("document", document);
lua.global.set("Math", Math);
lua.global.set("Wavedash", Wavedash);
const main = await fetch("./main.lua").then((r) => r.text());
await lua.doString(main);
</script>
</body>
</html>
SDK integration
With Wavedash bound as a global, Lua calls it using method-call syntax (:) so the SDK receives this:
-- window, document, Math, and Wavedash are bound as globals by index.html
local canvas = document:getElementById("gameCanvas")
local ctx = canvas:getContext("2d")
local function loop(now)
-- update + draw
window:requestAnimationFrame(loop)
end
-- ...install input handlers, kick off the loop...
Wavedash:updateLoadProgressZeroToOne(1.0)
Wavedash:init({ debug = true })
Any SDK method works: Wavedash:setAchievement("first_win", true), Wavedash:requestStats(), etc. See SDK setup and Functions reference for the full list.
wavedash.toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./web"
entrypoint = "index.html"