Solar2D (formerly Corona SDK) is a Lua framework with a first-party HTML5 export target. The export bundles your Lua into a WebAssembly build of the Solar2D runtime.
Export your game
Open the project in the Solar2D Simulator and choose File → Build → HTML5 (Beta). Pick an output folder outside the project directory (the builder refuses to write into the source folder) — ~/Desktop or /tmp works. Then move the contents into ./build/:
mv ~/Desktop/example-solar2d.html5/* build/
The output includes index.html, the engine JS bundle, and your game's compiled Lua.
HTML5 export is still labeled Beta in the Solar2D simulator, and there's no maintained headless CLI — the GUI builder is the supported path.
Content dimensions and orientation
Solar2D's config.lua content.width / content.height are always the portrait dimensions — Solar2D swaps them at runtime based on orientation.default in build.settings. A landscape game needs both sides set:
-- config.lua
application = {
content = {
width = 1080, -- portrait width → landscape height
height = 1920, -- portrait height → landscape width
scale = "letterBox",
fps = 60,
},
}
-- build.settings
settings = {
orientation = {
default = "landscapeRight",
supported = { "landscapeRight", "landscapeLeft" },
},
}
Without the orientation block, Solar2D's HTML5 build defaults to portrait and renders the canvas rotated 90° relative to what content.width/height suggest.
Make gameplay constants proportional to display.contentWidth / display.contentHeight so changing the content size in config.lua is the only knob you need:
local W, H = display.contentWidth, display.contentHeight
local PADDLE_H = H / 6 -- ~16.7% of height
local PADDLE_SPD = H * 5 / 6 -- pixels per second
SDK integration
Solar2D's HTML5 target supports a JavaScript Module Loader: any <name>.js file at the project root that defines a global object named <name> becomes loadable as require "<name>" in Lua. This is the clean way to call window.Wavedash from Lua without post-build patching the exported HTML.
Drop a wavedash.js next to your main.lua:
Calling Wavedash.init() is required. Your game stays hidden behind the Wavedash loading screen until you do. Call it once your game is ready to play.
// wavedash.js
var Wavedash = window.Wavedash;
var wavedash = {
init: function () {
Wavedash.init();
},
updateLoadProgressZeroToOne: function (p) {
Wavedash.updateLoadProgressZeroToOne(p);
},
};
Then call it from main.lua, guarded by system.getInfo("platform") so the Lua still runs fine in the desktop Simulator:
-- main.lua
if system.getInfo("platform") == "html5" then
local wavedash = require "wavedash"
wavedash.updateLoadProgressZeroToOne(1)
wavedash.init()
end
-- ... rest of your game ...
Call updateLoadProgressZeroToOne(...) with intermediate values during any async setup. init() automatically signals load completion, so call it last.
wavedash.toml
game_id = "YOUR_GAME_ID_HERE"
upload_dir = "./build"
entrypoint = "index.html"
Other SDK features
Expose each SDK method you need by adding another property on the wavedash global in wavedash.js:
var wavedash = {
// ... init / updateLoadProgressZeroToOne as above ...
uploadLeaderboardScore: function (id, score) {
Wavedash.uploadLeaderboardScore(id, score, true);
},
setAchievement: function (id) {
Wavedash.setAchievement(id, true);
},
};
uploadLeaderboardScore takes the leaderboard's ID (returned by getLeaderboard("name")), not the name itself. Lua doesn't have native promise/await semantics, so the cleanest path is to resolve the ID once at game start in wavedash.js and expose it as a Lua-readable global:
// in wavedash.js, after Wavedash is in scope:
Wavedash.getLeaderboard("high-scores").then(function (lb) {
if (lb.success) wavedash.highScoresId = lb.data.id;
});
Then from Lua:
wavedash.setAchievement("first_win")
-- once highScoresId is populated:
wavedash.uploadLeaderboardScore(wavedash.highScoresId, score)
See the SDK reference for the full API.
The build.settings html5.templateFile key is silently ignored by Solar2D's HTML5 builder (it's for other targets only). Don't try to wire the SDK through a custom HTML template — use the JavaScript Module Loader pattern above.