Login

Bevy

Bevy is a free and open source, data-driven game engine written in Rust. It is built around an ECS (Entity Component System) architecture: game state lives in components, and plain Rust functions ("systems") run over them in parallel. Bevy has no visual editor — projects are pure Cargo crates — which makes it a natural fit for a Makefile + CI workflow. First-class WebAssembly support means the same code base runs natively and in the browser.

Website: https://bevyengine.org

Tutorials


Makefile

This Makefile provides a simple, reproducible workflow for building Bevy projects natively and exporting them to the web (WASM via wasm-bindgen). It is designed for indie game development with automated version management and CI/CD deployment support.

Overview

The workflow is based on four core ideas:

  • Native builds are plain cargo build; web builds target wasm32-unknown-unknown and run wasm-bindgen to generate the JS glue (game.js + game_bg.wasm)
  • The HTML shell (index.html) is downloaded from the tools repository at export time, so every game ships the same loader
  • Version management is handled automatically from metadata.json or git commit hash
  • CI/CD targets enable automated build, versioning, and deployment

The templates live in the bevy-tools repository: copy example-makefile.make to Makefile and set PROJECT (it must match the crate name in Cargo.toml).

Version pinning: the wasm-bindgen CLI and the wasm-bindgen crate compiled into the game must be the same version. Pin the crate in Cargo.toml:

TOML
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "=0.2.100"

and keep WASM_BINDGEN_VERSION in the Makefile in sync. The CI builder image (git.teletypegames.org/internal/bevy-builder) ships the matching CLI — rebuild it with the new --build-arg WASM_BINDGEN_VERSION when bumping.

Configuration Variables

Variable Description Default
PROJECT Project / crate name (used in output filenames) bevydemo
WASM_BINDGEN_VERSION wasm-bindgen CLI version (must match Cargo.toml) 0.2.100
BIN_DIR Directory for the native binary bin
DIST_DIR Directory for exported artifacts dist
VERSION_FILE File storing version for CI/CD .version
INDEX_HTML_URL HTML shell downloaded at export time bevy-tools web/index.html

Usage

Build (default)

SH
make build
  • Runs cargo build --release and copies the binary to bin/$(PROJECT)

Run

SH
make run
  • Runs the project natively (cargo run)

Build WASM

SH
make wasm
  • Builds wasm32-unknown-unknown in release mode
  • Runs wasm-bindgen --target web producing dist/game.js and dist/game_bg.wasm
  • Requires rustup target add wasm32-unknown-unknown and the wasm-bindgen CLI (cargo install wasm-bindgen-cli --version 0.2.100)

Export

SH
make export VERSION=1.0.0
  • Requires a VERSION variable.
  • Runs the WASM build, downloads index.html, and packages everything into a versioned ZIP: bevydemo-1.0.0.html.zip
  • Cleans up the raw web files after packaging

Watch Mode

SH
make watch
  • Rebuilds on changes under src/ (requires fswatch)

Clean

SH
make clean
  • Removes bin/, dist/ and the Cargo target/ directory

VS Code Tasks

The tools repository also contains an example-tasks.json that can be copied to .vscode/tasks.json. It provides Run (cargo run, default build task, Cmd+Shift+B), Build & Run, Build WASM and Make build.

CI/CD Targets

make ci-version

  • Extracts version from metadata.json (if exists) or uses git short commit hash
  • If the branch is not main or master, prefixes version as dev-<version>-<branch>
  • Writes the final version to .version

make ci-export

  • Reads version from .version and runs make export with it

make ci-upload

  • Copies metadata.json to bevydemo-<version>.metadata.json
  • Uploads the ZIP and the metadata via SCP to the droparea
  • Requires environment variables: DROPAREA_SSH_PASSWORD, DROPAREA_PORT, DROPAREA_USER, DROPAREA_HOST, DROPAREA_TARGET_PATH

make ci-update

  • Calls $(UPDATE_SERVER)/update?platform=bevy&name=$(PROJECT)&version=<version>
  • Requires environment variables: UPDATE_SERVER, UPDATE_SECRET

Generated Artifacts

File Description
bin/bevydemo Native release binary
dist/game.js, dist/game_bg.wasm wasm-bindgen output (packaged, then removed)
bevydemo-<version>.html.zip Packaged web build, ready for deployment

Requirements

  • make, git, jq, zip, curl
  • Rust toolchain (cargo, rustup) with the wasm32-unknown-unknown target
  • wasm-bindgen CLI matching WASM_BINDGEN_VERSION
  • fswatch (only for watch mode)
  • sshpass and scp (for ci-upload target)

Pipeline

This document describes the Woodpecker CI pipeline used to build, export, upload, and publish a Bevy game project.

Overview

The pipeline logic is almost entirely encapsulated within the Makefile, which is called by each pipeline step. The pipeline performs the following steps:

  1. Version Extraction: make ci-version (alpine) — version from metadata.json or git.
  2. Build & Export: make ci-export in the git.teletypegames.org/internal/bevy-builder image (Rust toolchain with the wasm32-unknown-unknown target and the wasm-bindgen CLI preinstalled, built from builder.Dockerfile in bevy-tools) — builds and packages the ZIP.
  3. Upload Artifacts: make ci-upload — scp to the droparea (vps.teletype.hu:2223).
  4. Notify Update Server: make ci-update — calls the teletypegames /update endpoint with platform=bevy.

Copy example-woodpecker.yaml to .woodpecker.yaml and add the droparea_ssh_password / update_secret_key secrets in Woodpecker.

Note: a cold Bevy release build compiles several hundred crates — expect the build step to take considerably longer than the other engines' pipelines.

Demo project

bevy-demo is the reference project using these templates: an animated "TELETYPE GAMES" wave text (the same demo as ebitengine-demo), built on Bevy 0.16.