Bevy is an open source, data-driven game engine written in Rust. State lives in components, and plain Rust functions ("systems") run over them in parallel — this is ECS. There is no visual editor: a project is a Cargo crate, which fits a Makefile + CI workflow well. WebAssembly is first-class, so the same code runs natively and in the browser.
Website: https://bevyengine.org
Native builds are plain cargo build. Web builds target wasm32-unknown-unknown and run wasm-bindgen for the JS glue. The index.html shell is downloaded at export time, so every game uses the same loader.
Templates are in bevy-tools: copy example-makefile.make to Makefile and set PROJECT to the crate name from Cargo.toml.
Version pinning matters. The wasm-bindgen CLI and the wasm-bindgen crate must be the same version:
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "=0.2.100"
Keep WASM_BINDGEN_VERSION in the Makefile in sync. The CI image (git.teletypegames.org/build/bevy-builder) ships the matching CLI — rebuild it with a new --build-arg WASM_BINDGEN_VERSION when you bump.
| Variable | Description | Default |
|---|---|---|
PROJECT |
Project / crate name | bevydemo |
WASM_BINDGEN_VERSION |
CLI version, must match Cargo.toml | 0.2.100 |
BIN_DIR |
Native binary | bin |
DIST_DIR |
Exported artifacts | dist |
VERSION_FILE |
Version file for CI | .version |
INDEX_HTML_URL |
HTML shell | bevy-tools web/index.html |
make build # cargo build --release -> bin/$(PROJECT)
make run # cargo run
make wasm # release wasm + wasm-bindgen -> dist/game.js, dist/game_bg.wasm
make export VERSION=1.0.0 # wasm + index.html zipped as bevydemo-1.0.0.html.zip
make watch # rebuild on change under src/ (needs fswatch)
make clean # remove bin/, dist/ and target/
make wasm needs the target and the CLI:
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.100
Copy example-tasks.json to .vscode/tasks.json. Tasks: Run (default, Cmd+Shift+B), Build & Run, Build WASM, Make build.
| File | Description |
|---|---|
bin/bevydemo |
Native release binary |
dist/game.js, dist/game_bg.wasm |
wasm-bindgen output (packaged, then removed) |
bevydemo-<version>.html.zip |
Web build |
bevydemo-<version>-win-x64.zip |
Windows build (mingw cross-compile) |
bevydemo-<version>-linux-x64.zip |
Linux build (glibc) |
Local only: make, git, jq, zip, curl, the Rust toolchain with the wasm32-unknown-unknown target, a matching wasm-bindgen CLI, and fswatch for watch mode. CI images bring their own tools.
The pipeline is not in the game repo. Woodpecker asks the update server, and WarpEngine serves the whole config from /build/config (template lib/warp_engine/ci_templates/bevy.yaml.erb).
The repo needs three things:
# .woodpecker.yaml
platform: bevy
name: bevydemo # only when the software name differs from the repo name
metadata.jsonapplication_token Woodpecker secret: a WarpEngine ApplicationToken with update + upload scopesBuilder images come from the update server's ci_platforms config. Preview the served pipeline:
curl "https://teletypegames.org/build/config?platform=bevy"
| Step | What it does |
|---|---|
| 1. version | read the version from metadata.json, else the git short hash; outside main/master prefix it as dev-<version>-<branch> |
| 2. build | in the bevy-builder image: wasm build + wasm-bindgen, packed as the versioned zip |
| 3. binaries | native linux-x64 (glibc) and win-x64 via mingw (x86_64-pc-windows-gnu) |
| 4. upload | web zip, binary zips and <name>-<version>.metadata.json via POST /build/upload, X-Update-Secret header |
| 5. publish | POST /build/publish?platform=bevy |
The builder image is a debian Rust toolchain with the wasm32-unknown-unknown and x86_64-pc-windows-gnu targets, mingw-w64 and the wasm-bindgen CLI preinstalled, built from builder.Dockerfile in bevy-tools.
Binary details:
assets/ directory is packaged next to the binary — Bevy loads it at runtime, it is not embedded.<name>-<version>-<slug>.zip files as win_x64 / linux_x64 release assets.bevy-demo — animated "TELETYPE GAMES" wave text on Bevy 0.16, the same demo as ebitengine-demo.