# bevy_game_template is mostly a release pipeline with a game in it

> This template for the Bevy engine gives you a small example game, but the part that takes the work is the delivery side, a GitHub Actions workflow that builds releases for Windows, Linux, macOS and the web, development builds for Android and iOS, a CI job that checks the app on every native platform, and a documented path from a local cargo run to a published mobile build.

**NiklasEi/bevy_game_template** — Template for a Bevy game including CI/CD for web, Windows, Linux, macOS, iOS and Android

- Repository: https://github.com/NiklasEi/bevy_game_template
- Website: https://niklasei.github.io/bevy_game_template/
- Stars: 1,153 · Forks: 107
- Language: Rust
- License: CC0-1.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/niklasei-bevy-game-template

## The game is a placeholder, the pipeline is the product

The template is for a game using the Bevy engine, and it advertises out of the box builds for Windows, Linux, macOS, the web through Wasm, Android and iOS. The list of what you get starts with a small example game, which is the least interesting item, and then gets to the parts that matter. There is an easy setup for running the web build with trunk, a native run with `cargo run`, a workflow for GitHub Actions that creates releases for Windows, Linux, macOS and the web ready for distribution, the same workflow creating development builds for the mobile platforms, and a separate CI workflow that checks the application on all native platforms on every push. The releases are triggered by pushing a tag in the form `v[0-9]+.[0-9]+.[0-9]+*`, with `v1.1.42` given as the example. So the template's real contribution is the decision about how a Bevy game leaves your laptop, and that decision is made once, in files you can read.

## Three ways to run the same code

The getting started instructions give one command per target, and the differences are instructive. The native version is `cargo run`. The web build is `trunk serve`, which needs trunk installed with `cargo install --locked trunk` and the Wasm target with `rustup target add wasm32-unknown-unknown`, and it serves the app on port 8080 with an automatic rebuild and reload after code changes. The Android app is `cargo apk run -p mobile`, which needs the Android setup described in the Bevy example readme, and the iOS app needs Xcode from the app store with the simulator installed, the Rust targets added with `rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim`, and then `make run` inside the `/mobile` directory. The iOS route is the one that takes the most setup, and the fact that the template tells you to install the simulator from Xcode preferences is a small sign of how much of the mobile story is really Apple's tooling.

## One tag, six artefacts, and a CI job on every push

The release workflow is triggered by a tag, and the same workflow produces the mobile development builds as well, with two further workflows able to push to the stores after some setup. Underneath, there is a CI workflow that checks the application on all native platforms on every push, which means a broken build is caught before you tag rather than after. One operational warning is worth reading twice, because it catches people out. If you work in a private repository, macOS and Windows runners cost build minutes, while for public repositories the workflow runners are free. That single difference changes the economics of the setup, since a private project ends up paying for the macOS and Windows legs of every commit, and the template is structured so that those legs are unavoidable. The repository also carries a `credits` directory that you are told to keep up to date, because the release workflow automatically includes that directory in every build, so a missing credit is a licensing problem that only surfaces at release time.

## Mobile is where the template does real work

The Android section explains a tooling problem. `cargo-apk` is used to run the development app, but APKs can no longer be published in the store and `cargo-apk` cannot produce the required AAB. So there is setup for two Android related tools instead of one. The `package.metadata.android` section of `mobile/Cargo.toml` configures `cargo-apk` for the development flow, and `mobile/manifest.yaml` configures a custom fork of `xbuild`, which is what the `release-android-google-play` workflow uses to create the AAB. A forked build tool in a template is a thing to look at closely before you depend on it, since it will not follow upstream fixes on its own. The iOS side is described as pretty much what Bevy does for its own mobile example, which is a sensible delegation, and the author links blog posts on setting up the Android and iOS release workflows for the detail the README leaves out.

## The Cargo manifest makes performance trade-offs explicit

The manifest is worth reading as a set of decisions rather than a list of dependencies. Bevy is pinned at 0.20.0 with default features turned off and the `2d`, `3d` and `ui` features selected, with the comment that Bevy's defaults are those plus `audio`, and that audio is dropped here because it clashes with `bevy_kira_audio`, which is the audio crate that is used instead. The manifest also tells you that dropping the 3d or the 2d collection cuts compile time. The release profile is tuned for size, with an opt level of `s`, link time optimisation, one codegen unit and stripping, and there is a separate `dist` profile that inherits the release profile but raises the optimisation back to 3, so distribution builds and local builds can differ. The dev profile sets a global opt level of 1 but compiles dependencies at 3, which is the standard trick for keeping iteration fast without rebuilding the world. The comment on the release profile also records that trunk does not support custom profiles and that the same profile is used by xbuild for the Android AAB, which is a good example of a template absorbing a tool limitation and documenting it.

## Nix, trunk and the web build have their own corners

The development environment section is short and covers a specific problem. The template supports Nix, with a `flake.nix`, a `flake.lock` and a `nix/` directory, and the caveat is that nixgl is only used on non-NixOS Linux systems, where the evaluation needs to be impure:

```bash
nix develop --impure
```

And if you are using nixgl, you then run something like `gl cargo run`, while on other systems you use `cargo` as usual. The web side is a `Trunk.toml` and an `index.html` at the root, and the Trunk configuration exists because Trunk does not support custom Cargo profiles, which is the same limitation referenced in the manifest. The tree also has a `.cargo/` directory, and the manifest comments explain that the backend for `rand` and `getrandom` on Wasm is selected through rustflags in `.cargo/config.toml` for the `wasm32-unknown-unknown` target, so the Wasm specifics live in one file. The known issues section names a single one, that audio in web builds can have problems in some browsers, and attributes it to a general performance issue rather than to the audio itself.

## Licence, icons and the chores a template cannot avoid

The licence is CC0 1.0 Universal, which is about as permissive as a licence gets and unusual for a code template, with one carve-out. Some content of the `assets` directory and the Bevy icons in the `build` directory are excluded, and the credits file explains the detail, so the icons in particular are not yours to redistribute. The icon replacement procedure is the part of the setup that most templates get wrong, and this one is explicit. You replace `build/macos/icon_1024x1024.png` with a 1024 by 1024 icon and run `create_icns.sh`, or `create_icns_linux.sh` on Linux, with the note that the first needs a Mac and the second needs imagemagick and png2icns, and that the script has to be run inside the `build/macos` directory. The Windows icon is an `.ico` at `build/windows/icon.ico`, which doubles as the favicon for the web builds, and the guide walks through exporting it from Gimp. And the Android icon is the 256 pixel file from the macOS icon set copied into the mipmap folder and renamed. So a first release is a small chore, and doing it before you write any code is the advice the template is effectively giving.

## Conclusion

bevy_game_template suits a developer starting a Bevy project who wants the release plumbing decided once rather than in week two, especially someone shipping to the web first and to mobile later, since the mobile path is the part that is genuinely hard and is documented here. It is a poor fit if you want a framework or a set of systems, since the game in it is deliberately small, and it is a poor fit if you want the latest Bevy, since the dependency is pinned at 0.20.0 with a note about keeping some versions in sync by hand. Before you start, check three things: which Bevy version you want, since the manifest pins 0.20.0 and tells you to drop the 3d or 2d feature to cut compile time, whether you are on a public or private repository, because the runner minutes cost warning applies to private ones, and the licence, which is CC0 except for some assets and the Bevy icons in the build directory.

## FAQ

### What does bevy_game_template give me out of the box?

A small example game, out of the box builds for Windows, Linux, macOS, the web through Wasm, Android and iOS, a GitHub Actions workflow producing releases for the desktop and web targets plus mobile development builds, and a CI workflow that checks the app on all native platforms on every push.

### How do I run the Bevy game template on the web?

With `trunk serve`, after installing trunk with `cargo install --locked trunk` and the Wasm target with `rustup target add wasm32-unknown-unknown`. It serves on port 8080 and rebuilds and reloads automatically after code changes.

### How do I trigger a release from the Bevy template?

By pushing a tag in the form `v[0-9]+.[0-9]+.[0-9]+*`, for example `v1.1.42`. Note also that macOS and Windows runners cost build minutes in a private repository while public repositories get them free.

### Why does the Bevy template use a fork of xbuild for Android?

Because cargo-apk is used for the development app but can no longer produce the AAB that the store requires, so the mobile/Cargo.toml section configures cargo-apk while mobile/manifest.yaml configures a custom fork of xbuild, which the release-android-google-play workflow uses to build the AAB.

### What licence is bevy_game_template under?

CC0 1.0 Universal, except for some content of the assets directory and the Bevy icons in the build directory, which the credits file explains. The project is a Rust and Bevy template on edition 2024 with Bevy pinned at 0.20.0, and the last push to the repository was on 2026-10-10.

## Sources

- [License: CC0-1.0](https://github.com/NiklasEi/bevy_game_template/blob/main/LICENSE)
- [NiklasEi/bevy_game_template on GitHub](https://github.com/NiklasEi/bevy_game_template)
- [Project website](https://niklasei.github.io/bevy_game_template/)
- [README](https://github.com/NiklasEi/bevy_game_template/blob/main/README.md)
- [Releases](https://github.com/NiklasEi/bevy_game_template/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/niklasei-bevy-game-template
