Skip to content

Building

Estella projects can be built for two target platforms from the editor: Playable Ads (a single self-contained HTML file) and WeChat MiniGame (a directory structure ready for WeChat DevTools).

Build Targets

PlatformOutputDescription
Playable AdsSingle .html fileAll assets, WASM, and scripts inlined into one file. Designed for ad networks that require a single-file deliverable.
WeChat MiniGameDirectoryContains game.js, game.json, project.config.json, scene files, and assets. Ready to open in WeChat DevTools.

Toolchain Setup

Before your first build, the editor needs a C++ toolchain to compile the engine WASM binary. Open Build Settings and expand the Toolchain (emsdk) section. The status badge shows whether the toolchain is ready:

StatusMeaning
Ready (green)Emscripten, CMake, and Python are all detected and meet minimum versions
Not ready (red)One or more tools are missing or outdated

Auto Install

Click Auto Install to download a pre-packaged toolchain (~550–700 MB depending on platform). This includes Emscripten 5.0.0, CMake, and Python — no external dependencies required. Download progress is shown in a toast notification.

Manual Setup

If you already have emsdk installed, click Select emsdk and point to your emsdk root directory. The editor validates the path and detects versions automatically.

Engine Modules

Each build configuration can toggle which engine modules to include in the WASM binary:

ModuleDescription
Tilemap2D tilemap renderer
ParticlesParticle system
TimelineTimeline animation system
PostProcessPost-processing effects
Bitmap TextBitmap font rendering
SpineSpine skeletal animation (select runtime versions: 3.8, 4.1, 4.2)
PhysicsBox2D physics (compiled as a separate WASM module)

Disabling unused modules reduces the output WASM size. The engine is recompiled only when the module configuration changes; subsequent builds with the same configuration use a cached result.

Using the Build Panel

Open the Build panel from the editor toolbar. The panel has a three-column layout:

  1. Left sidebar — lists platforms and build configurations. Click a platform to filter, then select a configuration.
  2. Center detail — shows the selected configuration’s settings: scenes, script defines, and platform-specific options.
  3. Right output — displays build history, status, output size, and actions (Open Folder, Preview).

Creating a Build Configuration

Click Add in the toolbar to create a new configuration. Choose a name and target platform. The editor also provides pre-built Templates (accessible via the Templates button) for common setups like “Playable Production” or “WeChat Development”.

Running a Build

  1. Select a configuration from the sidebar
  2. Review the scenes list — click Add Current Scene to include the scene currently open in the editor
  3. Adjust platform-specific settings as needed
  4. Click Build (or press Cmd/Ctrl + B)

Build progress and logs are displayed in real time via a toast notification. When complete, you can click Open Folder to navigate to the output.

Build Templates

Click Templates in the toolbar to create a configuration from a preset. Built-in templates:

TemplatePlatformDescription
Facebook PlayablePlayable AdsOptimized for Facebook’s 2 MB limit with minification enabled
Google PlayablePlayable AdsOptimized for Google’s 5 MB limit
Playable DebugPlayable AdsDevelopment build with DEBUG define
WeChat ProductionWeChatSubpackage mode, portrait orientation
WeChat DebugWeChatSingle bundle with DEBUG define
WeChat Single FileWeChatSingle file bundle for simple games
WeChat LandscapeWeChatLandscape orientation for wide-screen games

You can also save any existing configuration as a custom template via Save as Preset in the detail panel.

Build Configuration

Each configuration contains:

SettingPurpose
NameHuman-readable label for this configuration
PlatformTarget platform: Playable Ads or WeChat MiniGame
ScenesList of .esscene files to include in the build
Script DefinesCompile-time defines (e.g. DEBUG). Accessible in your scripts via process.env.DEBUG.
Platform SettingsPlatform-specific options (see below)

Playable Ads Settings

SettingDescription
Startup SceneScene to load on startup (defaults to the first scene in the list)
Development BuildInclude debug info in the output
Minify CodeMinify bundled JavaScript for smaller output
Embed FontsInline font files into the HTML
Output PathWhere to write the output .html file (e.g. build/playable.html)
Enable Built-in CTAShow a built-in “Install Now” call-to-action button
CTA URLDestination URL when the CTA button is clicked

WeChat MiniGame Settings

SettingDescription
AppIDWeChat MiniGame AppID. Use touristappid for testing without a registered app.
VersionVersion string (e.g. 1.0.0)
Screen OrientationPortrait or Landscape
Bundle ModeSubpackage (recommended), Single Package, or Single File
Output DirectoryWhere to write the output directory (e.g. build/wechat)

Asset Export Configuration

The build system determines which assets to include using three modes, configurable per folder in the editor:

ModeBehavior
auto (default)Only include assets that are referenced by scenes or prefabs in the build
alwaysInclude all assets in the folder regardless of references
excludeNever include assets from this folder

Asset export modes are stored in .esengine/asset-export.json:

{
"version": "1.0",
"folders": {
"assets/ui": "always",
"assets/debug": "exclude"
}
}

Folders inherit their parent’s mode. For example, if assets/sprites is set to always, all files under assets/sprites/enemies/ are also included.

Build Pipeline

When you click Build, the editor runs the following pipeline:

1. Asset Collection

The build scans scene files and recursively collects:

  • Textures referenced by Sprite, SpineRenderer, and other components
  • Materials and their shader dependencies
  • Spine atlas files and their texture pages
  • Bitmap font files and their glyph textures
  • Nested prefabs and their transitive asset references

2. Atlas Packing

Referenced images are packed into texture atlas pages (max 2048x2048 by default). Scene data is rewritten to use atlas coordinates, so sprites automatically reference the packed atlas at runtime.

3. Material Compilation

.esmaterial files are compiled to JSON, resolving shader references and inlining property values.

4. Script Bundling

User scripts from the src/ directory are compiled and bundled with esbuild. The esengine SDK is treated as an external module — on Playable it is inlined, on WeChat it is loaded from sdk.js.

5. Asset Build Transforms

Before writing assets, the pipeline applies build transforms to JSON-based assets that contain references needing rewriting. For example, prefabs and animation clips contain texture paths that must be remapped to atlas coordinates.

Transforms are registered on the AssetTypeEntry via registerAssetBuildTransform(). The built-in transforms are:

Asset TypeTransform
prefabResolves UUID refs to build paths, rewrites atlas-packed texture refs with uvOffset/uvScale
anim-clipRewrites frame texture paths to atlas pages, adds atlasFrame metadata for UV calculation

Both platform emitters call entry.buildTransform(content, artifact) generically — no per-type branching. To add a custom asset type that needs build-time rewriting, register a transform in your editor plugin:

import { registerAssetBuildTransform } from 'esengine';
registerAssetBuildTransform('my-custom-type', (content, context) => {
const artifact = context; // BuildArtifact
const data = JSON.parse(content);
// ... rewrite asset references ...
return JSON.stringify(data);
});

6. Platform Emission

The final output is produced for the target platform:

  • Playable Ads — assembles a single HTML file with all assets base64-encoded inline
  • WeChat MiniGame — writes a directory with game.js, game.json, project.config.json, scenes, assets, and WASM files

Output Structure

Playable Ads

build/
playable.html # single self-contained file

WeChat MiniGame

build/wechat/
project.config.json # WeChat DevTools project config
game.json # MiniGame manifest
game.js # entry point (engine init + user scripts)
esengine.js # WASM engine loader
esengine.wasm # engine WASM binary
sdk.js # SDK runtime
spine.js / spine.wasm # Spine runtime (if Spine is enabled)
physics.js / physics.wasm # physics engine (if physics is enabled)
atlas_0.png # packed texture atlas pages
asset-manifest.json # addressable asset manifest
scenes/
Level1.json # exported scene data
assets/
... # non-packed asset files

Addressable Manifest

Both platforms generate an asset-manifest.json that maps asset UUIDs to runtime paths. This enables the runtime to resolve assets by UUID or address and to reconstruct atlas frames from packed pages.

{
"version": "2.0",
"groups": {
"default": {
"bundleMode": "together",
"labels": [],
"assets": {
"uuid-1": {
"path": "assets/sprites/player.png",
"type": "texture",
"size": 1024,
"labels": ["character"]
}
}
}
}
}

Build Hooks

Each configuration can define pre-build and post-build hooks to automate custom steps. Add hooks in the collapsible Build Hooks section of the configuration detail panel. Each hook has a phase (pre or post) and a type (copy-files or run-command).

Copy Files

Recursively copy a directory to another location. Optionally filter files by glob pattern.

FieldDescription
fromSource directory path
toDestination directory path
patternOptional filename filter (e.g. *.png, *.json) — only matching files are copied

Both from and to support path variables:

VariableResolves To
${projectDir}Absolute path to the project root
${outputPath}Full path to the output file (e.g. build/playable.html)
${outputDir}Directory containing the output (e.g. build/)

Run Command

Execute a shell command with the project root as the working directory (cwd).

FieldDescription
commandThe executable to run (e.g. node, python3, bash)
argsOptional array of string arguments passed to the command

The command receives:

  • Working directory — the project root (same as the editor’s project path)
  • Arguments — the literal strings from the args array (no variable substitution)
  • Stdout/stderr — captured and logged to the build console (stdout truncated to 200 chars)
  • Exit code — non-zero exits will fail the build

Hook Examples

Copy extra assets into the WeChat output after building:

{
"phase": "post",
"type": "copy-files",
"config": {
"from": "${projectDir}/assets/extras",
"to": "${outputDir}/assets/extras",
"pattern": "*.png"
}
}

Run a texture compression script before building (CWD is the project root, so relative paths work):

{
"phase": "pre",
"type": "run-command",
"config": {
"command": "node",
"args": ["scripts/compress-textures.js", "--input", "assets/textures", "--quality", "80"]
}
}

The script receives args as process.argv.slice(2):

scripts/compress-textures.js
const args = process.argv.slice(2);
// args = ["--input", "assets/textures", "--quality", "80"]
// process.cwd() = project root directory
const inputDir = args[args.indexOf('--input') + 1]; // "assets/textures"
const quality = args[args.indexOf('--quality') + 1]; // "80"

Post-build hook to copy the output to a deploy folder:

{
"phase": "post",
"type": "copy-files",
"config": {
"from": "${outputDir}",
"to": "${projectDir}/deploy"
}
}

Config JSON Format

Build configurations are stored in editor-state.json. Each config follows this structure:

{
"id": "playable-prod",
"name": "Playable - Production",
"platform": "playable",
"scenes": ["assets/scenes/main.esscene"],
"defines": [],
"hooks": [
{
"phase": "post",
"type": "run-command",
"config": { "command": "open", "args": ["${outputDir}"] }
}
],
"playableSettings": {
"startupScene": "assets/scenes/main.esscene",
"isDevelopment": false,
"minifyCode": true,
"embedFonts": true,
"outputPath": "build/playable.html",
"enableBuiltinCTA": false,
"ctaUrl": ""
}
}

For WeChat configurations, replace playableSettings with wechatSettings:

{
"id": "wechat-prod",
"name": "WeChat - Production",
"platform": "wechat",
"scenes": ["assets/scenes/main.esscene"],
"defines": [],
"hooks": [],
"wechatSettings": {
"appId": "wx1234567890",
"version": "1.0.0",
"bundleMode": "subpackage",
"outputDir": "build/wechat",
"orientation": "portrait"
}
}

Config Import & Export

Build configurations can be exported as JSON for backup or team sharing:

  • Export — click the Export button in the toolbar to save all configs to a .json file
  • Import — click Import to load configs from a previously exported file

Custom templates saved via Save as Preset are stored in .esengine/build-templates/ as JSON files. These can be committed to version control for team sharing.

Project Settings

Build behavior is also influenced by project-level settings:

SettingEffect
Spine versionIncludes Spine runtime WASM module in the build
Enable physicsIncludes physics WASM module and generates physics config
Physics gravitySets the gravity vector in the physics config
Physics timestepSets the fixed simulation timestep