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/woodpecker/platforms/bevy/pipeline.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. On teletypegames.org the builder is bevy-ttg: the bevy-builder image with the crates of every TTG Rust project preloaded into the cargo registry, so the build steps no longer download several hundred crates each (a new dependency is still downloaded as usual). The helper steps (version, upload, publish) run in the ci-tools image, which has git, jq, curl and zip preinstalled, so they install nothing. Preview the served pipeline:
curl "https://teletypegames.org/build/config?platform=bevy"
| Step | What it does |
|---|---|
| 1. version | the engine's shared step (since WarpEngine 1.7): the version from metadata.json; on a tag a version tag has to match it; outside the repo's default branch and on a dev-<branch> tag dev-<version>-<branch>, with no version dev-<commit>; write .version |
| 2. build | in the builder image (bevy-ttg on teletypegames.org): 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 | on the tag only: web zip, binary zips and <name>-<version>.metadata.json via POST /build/upload, X-Update-Secret header |
| 5. publish | on the tag only: POST /build/publish?platform=bevy |
| 6. tag | the engine's shared step (since WarpEngine 1.9), after a push only: a new version in the source gets its v<version> tag, whose pipeline runs the steps marked on the tag only; a version tagged already releases nothing; a dev build moves the branch's dev-<branch> tag onto the commit, so the newest dev build is published. See Versions and releases on the WarpEngine page |
Raising the version is the release: a push builds and tags, and the tag's pipeline uploads and publishes (WarpEngine 1.9). A push that leaves the version as it is only builds.
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.