Contributing Guide
Renzora is open source and welcomes contributions — this guide covers the workflow, code style, and CI checks your pull request has to pass.
Code of conduct
Be respectful, constructive, and collaborative. Harassment, trolling, and unconstructive negativity are not tolerated. We're building something together — treat others the way you'd want to be treated.
Getting started
- Fork the engine repo on GitHub.
- Clone your fork and check out a branch from
main. - Make your changes, following the guidelines below.
- Run the checks (
renzora test,renzora check) locally — both run in the container. - Push to your fork and open a pull request against
main.
git clone https://github.com/YOUR_USERNAME/engine.git
cd engine
git checkout -b fix-spotlight-shadow
renzora init # one-time: build/pull the toolchain image
# make changes...
renzora shell -- cargo fmt # rustfmt inside the container
renzora check # clippy (warnings denied) in the container
renzora test # test suite in the container
git commit -m "Fix spotlight shadow not updating when range changes"
git push origin fix-spotlight-shadow
If you're looking for a first contribution, check for issues labeled good first issue or help wanted.
Development setup
The full build story — the one-binary / editor-as-removable-cdylib model and the Docker toolchain image — is documented in Building from a Checkout. Every build runs in the container; the short version:
renzora run # build the workspace and run the EDITOR
renzora run runtime # run the shipped-game shape (same binary, --no-editor)
renzora run -- --server # run a headless dedicated server (--server)
Renzora's canonical build is the container — it guarantees your
bevy_dyliband engine build hash match everyone else's, which is what keeps the plugin ABI compatible, and it's required for cross-platform/release builds. A native (no-Docker) build of your host platform is also supported viacargo renzora(source-first, so the host and its plugins share onebevy_dylib); prefer the container when results must match the canonical env. The editor is the removablerenzora_editorcdylib bundle that the binary dlopens from beside itself; there is noeditorcompile-time feature — the only build features on therenzorabinary areruntime(default) andwasm.
Toolchain
- The build runs in the pinned
ghcr.io/renzora/*images (a sharedbaseplus one per platform) — you only need Docker and Git. The Rust version, C/C++ toolchain, linkers (clang/mold/rust-lld), and the Bevy system libraries are all baked into the images; you install none of them locally. The CLI pulls only the images a command needs. - Rust/Cargo is needed only to install the CLI (
cargo install renzora), not to build the engine. - The Rust version is pinned in two lockstep files:
docker/base/Dockerfile(FROM rust:1.95.0-bookworm, the container) andrust-toolchain.toml(nativecargo renzorabuilds). The project does not require nightly. - Linux uses
moldand Windows usesrust-lldinside the image (MSVClink.exehits the 65535-object limit onbevy_dylib) — that linker setup is fixed in the container, another reason the build is container-only.
Heads-up: hardware ray-traced GI ships via the optional
renzora_solariplugin (Bevy Solari), enabled by thebevy_solariBevy feature in the workspaceCargo.tomland activated at runtime only on RT-capable GPUs — see Solari ray-traced GI. There is still no--features solaribuild flag; Solari is a drop-in plugin, not a build variant. Lumen's separateLumenQuality::Hwrttier remains an unimplemented placeholder and renders nothing.
What to contribute
| Area | How |
|---|---|
| Bug fixes | Browse the issue tracker. |
| Documentation | Edit the markdown under docs/ in the website repo (this site), not the engine repo. |
| Editor panels | Register a native bevy_ui panel with the App extension APIs register_shell_panel(id, title, icon, category) + register_panel_content(id, scroll, build_fn). See Editor Panels. |
| Scripting functions | Add Lua bindings in renzora_scripting (or a domain crate's ScriptExtension). Rhai is a subset — see Rhai before assuming parity. |
| Post-process effects | Annotate a settings struct with #[renzora_macros::post_process(...)] and renzora::add! the plugin. See Post-Processing. |
| Plugins | Self-register with renzora::add!(MyPlugin). See Building Plugins. |
| Export targets | Improve a platform lane in docker/build-all.sh. |
The editor has no
EditorPaneltrait you "implement and register" — panels are plain bevy_ui content functions registered through the twoAppextension methods above. Anything claiming an eguiEditorPaneltrait is stale (egui was fully removed).
Code style
Formatting
Use default rustfmt. Run cargo fmt before committing, and don't hand-format in ways that conflict with it.
Naming
- Types:
PascalCase—BlueprintGraph,ScriptComponent,LumenLighting,DockTree. - Functions / variables:
snake_case—spawn_entity,handle_input. - Constants:
SCREAMING_SNAKE_CASE. - Modules:
snake_case, matching the file name.
General conventions
- Follow existing patterns in the module you're touching.
- Use Bevy's ECS idioms — systems, components, resources, events.
- Prefer
///doc comments on public items and//!at the top of a module. - Avoid
unwrap()in production code paths; use proper error handling orexpect()with a message. - Keep changes minimal — don't refactor unrelated code or reformat files you didn't change.
Testing
Tests live in #[cfg(test)] mod tests blocks alongside the code. Run the suite the same way CI does — in the container, via the CLI:
renzora test
renzora test -- scripting::tests # a specific module
Focus on logic, serialization round-trips, and edge cases:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn blueprint_graph_roundtrips() {
let original = sample_graph();
let serialized = ron::to_string(&original).unwrap();
let restored: BlueprintGraph = ron::from_str(&serialized).unwrap();
assert_eq!(original, restored);
}
}
What's worth a test: new data structures (serialize/deserialize round-trips), new algorithms (correctness + edge cases), new components (registration and defaults), and networking round-trips (e.g. crates/renzora_network/tests/host_server.rs validates host-mode promotion to an in-process HostClient).
Continuous integration
CI runs on every push and pull request to main (.github/workflows/test.yml). Both jobs run inside the shared base image ghcr.io/renzora/base:latest, so the runner needs nothing installed — rustc 1.95 and the Linux dev libs are baked into the base (the per-platform cross toolchains aren't needed to test first-party crates).
CI invokes
cargo testandcargo clippyinside the image. Therenzora test/renzora checkCLI commands wrap those same cargo invocations in the container, so they reproduce CI locally — run those, not a nativecargo.
Each job runs this inside the image (reproduce with renzora test / renzora check):
# Test job — first-party crates only; the vendored Bevy-ecosystem crates are excluded
cargo test --workspace \
--exclude bevy_gauge --exclude bevy_hanabi --exclude bevy_mod_outline \
--exclude bevy_silk --exclude vleue_navigator \
--exclude bevy_mod_openxr --exclude bevy_mod_xr --exclude bevy_xr_utils
# Clippy job — warnings are denied
cargo clippy --workspace --no-deps \
--exclude bevy_gauge --exclude bevy_hanabi --exclude bevy_mod_outline \
--exclude bevy_silk --exclude vleue_navigator \
--exclude bevy_mod_openxr --exclude bevy_mod_xr --exclude bevy_xr_utils \
-- -D warnings \
-A clippy::too_many_arguments \
-A clippy::type_complexity
The vendored crates (bevy_*, vleue_navigator) are third-party code copied into the tree — they still build as dependencies, but their own test suites are skipped to avoid re-testing upstream. too_many_arguments and type_complexity are allowed because they're inherent to Bevy systems and queries. New first-party crates are covered automatically via --workspace.
Pull requests
- Open an issue first for non-trivial changes so the approach can be discussed.
- One concern per PR — don't mix a bug fix with a feature or a refactor.
- Branch from
mainwith a descriptive name (fix-spotlight-shadow,add-cylinder-collider). - Write tests for new functionality when the module already has coverage.
- Update documentation (this website's
docs/) when you change public APIs or add features. - During review, push additional commits — don't force-push mid-review.
PR checklist
- [ ]
cargo fmtapplied (viarenzora shell), no unrelated formatting changes - [ ]
renzora check(clippy, warnings denied) is clean - [ ]
renzora testpasses - [ ] New tests added where applicable
- [ ] Branch is up to date with
main
Commit messages
Match the existing style:
- Imperative present tense: "Add ...", "Fix ...", "Update ...", "Refactor ..."
- Under ~72 characters, no trailing period.
- Say what changed and why.
Add cylinder collider component with radius and height
Fix spotlight shadow not updating when range changes
Refactor blueprint codegen to support multiple output pins
Reporting issues
Search existing issues first to avoid duplicates. For a bug report, include:
- Steps to reproduce, expected vs actual behavior.
- Environment — OS, GPU, and
rustc --version. - Run mode — editor (bundle present), shipped game (
--no-editor),--server, or--host. Note that the only build features areruntime(default) andwasm; there is noeditorfeature to report. - Crash logs — the editor writes
~/.renzora/crashes/last_crash.txt(plus a native dialog); the shipped game silently appendscrash.logbeside the executable. Attach the relevant one.
License
The engine is dual-licensed under MIT OR Apache-2.0 (LICENSE-MIT and LICENSE-APACHE at the repo root). By contributing, you agree your contributions are licensed under the same terms, without additional conditions.
What's next?
- Building from Source — the full build, aliases, and Docker cross-compile flow
- Architecture — the one-binary, editor-as-removable-cdylib model
- Building Plugins — extend the engine with
renzora::add!