A forward-looking implementation of the Decentraland protocol, written in rust on the Bevy engine.
One engine, three products:
| Target | What it is | Where it ships |
|---|---|---|
| Web client | The engine compiled to WebAssembly (WebGPU), with a React DOM HUD, running in the browser | @dcl-regenesislabs/bevy-explorer-web → served at decentraland.zone/bevy-web |
| Desktop client | Native binary for macOS / Linux / Windows, same React HUD rendered through an offscreen CEF webview | Releases |
| Headless server | Authoritative scene server, no rendering — drop-in replacement for @dcl/hammurabi-server |
@dcl-regenesislabs/bevy-headless-server (npm) |
This project's goals are to:
- document current and future protocol standards
- experiment with changes to the protocol
- increase the field of alternative Explorers
- prioritize solid fundamentals, extensibility, and the use of modern open-source frameworks
| Path | What |
|---|---|
src/ |
binaries: decentra-bevy (client), decentra-bevy-cef (CEF render-process helper), headless (scene server) |
crates/ |
the engine, split by domain (scene_runner, comms, avatar, ipfs, dcl_deno, system_bridge, …) |
react-web/ |
the React DOM HUD — one codebase for both web and desktop; see react-web/README.md |
react-web/bridge-scene/ |
headless SDK7 "super-user" scene that relays engine ↔ React over a BroadcastChannel |
deploy/web/ |
the published web tree: engine boot module + workers + wasm, bridge scene, service worker |
deploy/headless/ |
npm launcher + per-platform packaging for the headless server |
deploy/macos, deploy/linux |
desktop packaging (installer, AppImage) |
docs/, react-web/docs/ |
design notes and backlog |
Common to every target:
- rust (stable; the wasm build needs nightly — see below)
- protoc —
brew install protobuf - node 20+ (24 in CI) for the React HUD and bridge scene
- optionally just —
just --listfor the dev entry points used below
Platform libraries (needed by the native and headless builds):
- linux:
sudo apt-get install --no-install-recommends libasound2-dev libudev-dev ninja-build clang cmake pkg-config libssl-dev libx11-dev libgl1-mesa-dev libxext-devplus ffmpeg dev packages (libavcodec-dev libavformat-dev libavutil-dev libavfilter-dev libavdevice-dev) - macos:
brew install ffmpeg@6 pkg-config ninjaandexport PKG_CONFIG_PATH=/opt/homebrew/opt/ffmpeg@6/lib/pkgconfig - windows: install clang/LLVM and set
LIBCLANG_PATH; unzip ffmpeg 6.0 shared, setFFMPEG_DIRto its root and addffmpeg\bintoPATH(ninja and cmake ship with visual studio)
The engine is compiled to wasm and boots in the React page's own document (no iframe): the canvas sits behind the HUD, and the bridge scene relays between them.
rustup toolchain install nightly-2026-04-15 --target wasm32-unknown-unknown --component rust-src
cargo install wasm-pack
just wasm # builds the wasm into deploy/web/engine/pkg, then serves react-web and opens a browserjust wasm is the whole loop: wasm-pack build, re-bundle the sandbox worker (it inlines the wasm glue, so it must be rebuilt with the wasm), npm install in react-web and react-web/bridge-scene, then npm run dev.
Useful URLs once the dev server is up:
http://localhost:5173/— real engine + live bridge-scene preview on :8100http://localhost:5173/?mock=1— full HUD on a fake bridge, no engine build neededhttp://localhost:5173/?bundled=1— engine loads the exported static bridge scene, i.e. exactly what ships
Requires a WebGPU-capable browser. Deployment topology (versioned CDN base, same-origin rules, COEP service worker) is documented in react-web/README.md.
The desktop build renders the same React HUD through an offscreen CEF webview (react-hud-cef, a default feature). Without the HUD bundle the app runs with no UI at all.
just setup-cef # once per machine: exports the CEF distribution to ~/.local/share/cef
export CEF_PATH=$HOME/.local/share/cef
# linux only, to run from the target dir:
export LD_LIBRARY_PATH=$CEF_PATH:$LD_LIBRARY_PATH
just native-release # bundles the HUD if stale, then builds + runs everythingjust native-debug is the same in debug. Both pass extra arguments through:
just native-release --realm https://realm-provider-ea.decentraland.org/main --position 52,-52--base-domain retargets the backend hosts (auth, comms, places, worlds, social, ...) at another deployment's domain. renderer-artifacts (sdk6 adaption layer) and builder-items (inspector asset catalog) stay on decentraland.org — they have no other deployment:
just native-release --base-domain interconnected.online --position 0,0On web the same thing is the ?baseDomain= query param, e.g. ?baseDomain=interconnected.online. Without the param, the hosting origin decides: a page served under decentraland.zone keys to zone backends, anything else to org.
One service at a time: each has its own flag taking a full base url that replaces that service's composition while the rest keep following the domain (--help, "Service endpoints"). The same names are web query params, e.g. --catalyst http://localhost:3000 / ?catalyst=http://localhost:3000:
just native-release --places http://localhost:5000 --realm-provider http://localhost:8000Doing it by hand instead of via just:
./scripts/gen-ts-bindings.sh # TS types for the system API (generated, gitignored)
cd react-web && npm ci && (cd bridge-scene && npm ci) && npm run bundle:native && cd ..
cargo build --release --package dcl_deno_ipc # scene runtime sidecar
cargo build --release # decentra-bevy + decentra-bevy-cef
cargo run --releaseTo build without CEF at all (the engine's own bevy-ui HUD instead of React):
cargo run --release --no-default-features --features "livekit,ffmpeg,inspect,social"An authoritative scene server with no renderer — the SDK spawns it for scenes with authoritativeMultiplayer enabled.
npx @dcl-regenesislabs/bevy-headless-server --realm http://localhost:8000From source (the binary is feature-gated out of default builds, and execs the sidecar from its own directory, so both land in target/release):
cargo build --release -p dcl_deno_ipc
cargo build --release --bin headless --no-default-features --features headless,livekit
./target/release/headless --realm <url> --location 0,0 --server-mode--orchestrated runs it as a multi-scene worker driven over stdin/stdout instead. See deploy/headless/launcher/README.md for the CLI contract and docs/headless-sdk-preview.md for how it replaces hammurabi in the SDK preview.
cargo run --release --bin decentra-bevy -- --help lists every flag with its description.
The launch parameters shared with the web build — realm, spawn parcel, ui scene, portables, preview, editor, content server, pulse server, imposter source, base domain, fps logging, gpu bytes per frame — are declared once, in crates/system_api_types/src/launch_options.rs: each field is the native --flag, the engine_run options key and the entry-url query param, and the react page's parameter table is generated from it. Which of those a link may set without a warning is the page's own policy (react-web/src/lib/launchGate.ts). Native-only flags (rendering, imposters, debug, the --builtin-* ui pieces) live on DecentralandArguments in src/lib.rs.
cargo test --all # engine
npm test --prefix react-web # HUD, deterministic (vitest, no engine)
npm run test:e2e --prefix react-web # HUD against a real engine (playwright, needs a GPU)react-web/review.md is the pre-merge checklist for anything under react-web/.
.github/workflows/ci.yml is the most accurate source of build information — it covers fmt, clippy, the test matrix, a headless smoke test, and the web build/deploy.
- Web — every push to
mainpublishes@dcl-regenesislabs/bevy-explorer-web(npm + CDN) fromdeploy/web. - Headless —
publish-headless.ymlpublishes a snapshot onnextper main push; releasing to SDK previews means dispatching it withdist_tag=latest. - Desktop —
package.yml, dispatched manually, cuts a GitHub prerelease (linux + windows; the macOS leg is disabled pending notarization secrets).
Built by DCL Regenesis Labs — dclregenesislabs.xyz
