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
| Platform | Output | Description |
|---|---|---|
| Playable Ads | Single .html file | All assets, WASM, and scripts inlined into one file. Designed for ad networks that require a single-file deliverable. |
| WeChat MiniGame | Directory | Contains 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:
| Status | Meaning |
|---|---|
| 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:
| Module | Description |
|---|---|
| Tilemap | 2D tilemap renderer |
| Particles | Particle system |
| Timeline | Timeline animation system |
| PostProcess | Post-processing effects |
| Bitmap Text | Bitmap font rendering |
| Spine | Spine skeletal animation (select runtime versions: 3.8, 4.1, 4.2) |
| Physics | Box2D 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:
- Left sidebar — lists platforms and build configurations. Click a platform to filter, then select a configuration.
- Center detail — shows the selected configuration’s settings: scenes, script defines, and platform-specific options.
- 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
- Select a configuration from the sidebar
- Review the scenes list — click Add Current Scene to include the scene currently open in the editor
- Adjust platform-specific settings as needed
- 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:
| Template | Platform | Description |
|---|---|---|
| Facebook Playable | Playable Ads | Optimized for Facebook’s 2 MB limit with minification enabled |
| Google Playable | Playable Ads | Optimized for Google’s 5 MB limit |
| Playable Debug | Playable Ads | Development build with DEBUG define |
| WeChat Production | Subpackage mode, portrait orientation | |
| WeChat Debug | Single bundle with DEBUG define | |
| WeChat Single File | Single file bundle for simple games | |
| WeChat Landscape | Landscape 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:
| Setting | Purpose |
|---|---|
| Name | Human-readable label for this configuration |
| Platform | Target platform: Playable Ads or WeChat MiniGame |
| Scenes | List of .esscene files to include in the build |
| Script Defines | Compile-time defines (e.g. DEBUG). Accessible in your scripts via process.env.DEBUG. |
| Platform Settings | Platform-specific options (see below) |
Playable Ads Settings
| Setting | Description |
|---|---|
| Startup Scene | Scene to load on startup (defaults to the first scene in the list) |
| Development Build | Include debug info in the output |
| Minify Code | Minify bundled JavaScript for smaller output |
| Embed Fonts | Inline font files into the HTML |
| Output Path | Where to write the output .html file (e.g. build/playable.html) |
| Enable Built-in CTA | Show a built-in “Install Now” call-to-action button |
| CTA URL | Destination URL when the CTA button is clicked |
WeChat MiniGame Settings
| Setting | Description |
|---|---|
| AppID | WeChat MiniGame AppID. Use touristappid for testing without a registered app. |
| Version | Version string (e.g. 1.0.0) |
| Screen Orientation | Portrait or Landscape |
| Bundle Mode | Subpackage (recommended), Single Package, or Single File |
| Output Directory | Where 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:
| Mode | Behavior |
|---|---|
auto (default) | Only include assets that are referenced by scenes or prefabs in the build |
always | Include all assets in the folder regardless of references |
exclude | Never 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 Type | Transform |
|---|---|
prefab | Resolves UUID refs to build paths, rewrites atlas-packed texture refs with uvOffset/uvScale |
anim-clip | Rewrites 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 fileWeChat 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 filesAddressable 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.
| Field | Description |
|---|---|
| from | Source directory path |
| to | Destination directory path |
| pattern | Optional filename filter (e.g. *.png, *.json) — only matching files are copied |
Both from and to support path variables:
| Variable | Resolves 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).
| Field | Description |
|---|---|
| command | The executable to run (e.g. node, python3, bash) |
| args | Optional 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
argsarray (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):
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
.jsonfile - 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:
| Setting | Effect |
|---|---|
| Spine version | Includes Spine runtime WASM module in the build |
| Enable physics | Includes physics WASM module and generates physics config |
| Physics gravity | Sets the gravity vector in the physics config |
| Physics timestep | Sets the fixed simulation timestep |