This commit is contained in:
Matthew Deville 2026-09-28 12:18:10 +02:00
parent bcf542f963
commit df85367414
14 changed files with 590 additions and 488 deletions

3
.gitignore vendored
View file

@ -1,4 +1,3 @@
dist
target
static
result
.direnv

871
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,11 @@
[workspace]
members = ["app", "server"]
resolver = "3"
[package]
edition = "2024"
name = "website"
version = "0.1.0"
[dependencies]
avian2d = "0.7"
bevy = { version = "0.19", default-features = false, features = ["2d"] }
[profile.dev.package."*"]
opt-level = 3

9
Trunk.toml Normal file
View file

@ -0,0 +1,9 @@
[build]
dist = "dist"
target = "web/index.html"
[serve]
# Required in order to receive 404s for missing assets, which is what Bevy expects.
no_spa = true
# Open a browser tab once the initial build is complete.
open = true

View file

@ -1,2 +0,0 @@
[build]
target = "wasm32-unknown-unknown"

View file

@ -1,7 +0,0 @@
[package]
edition = "2024"
name = "app"
version = "0.1.0"
[dependencies]
bevy = { version = "0.19", default-features = false, features = ["2d"] }

View file

@ -1,35 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
PROFILE="${1:-release}"
if [ "$PROFILE" = "dev" ]; then
PROFILE_DIR="debug"
CARGO_FLAGS="--features=bevy/dynamic_linking"
else
PROFILE_DIR="release"
CARGO_FLAGS="--release"
fi
cargo build $CARGO_FLAGS --target wasm32-unknown-unknown -p app
mkdir -p static
# Drop stale bindgen / compression outputs from prior builds.
rm -f static/2dscene*
wasm-bindgen --out-name 2dscene \
--out-dir static \
--target web \
"target/wasm32-unknown-unknown/$PROFILE_DIR/app.wasm"
if [ "$PROFILE" != "dev" ]; then
wasm-opt -Oz --all-features -o static/2dscene_bg.wasm static/2dscene_bg.wasm
# Precompress assets Axum will negotiate via Accept-Encoding.
for f in static/2dscene_bg.wasm static/2dscene.js; do
gzip -9 -k -f "$f"
brotli -q 11 -f -k "$f"
done
fi
cp web/index.html static/

View file

@ -33,36 +33,27 @@
inherit system overlays;
};
rustToolchain = rustPkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
cargoLock = fromTOML (builtins.readFile ./Cargo.lock);
wasmBindgen = pkgs.lib.findFirst (
pkg: pkg.name == "wasm-bindgen"
) (throw "Could not find wasm-bindgen package") cargoLock.package;
wasm-bindgen-cli = pkgs.buildWasmBindgenCli rec {
src = pkgs.fetchCrate {
pname = "wasm-bindgen-cli";
version = wasmBindgen.version;
hash = "sha256-pcecKQd7E8Opw6bkFoE569epUi7gh5qpQF1e5PJY6V8=";
};
cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
inherit src;
inherit (src) pname version;
hash = "sha256-vmUrWVU7kPJJxO5qIVeAkwQyWDELO1Z4Z5gitz2kco8=";
};
};
runtimeDeps = with pkgs; [
alsa-lib
udev
vulkan-loader
wayland
libxkbcommon
];
in
{
devShells.default = pkgs.mkShell {
buildInputs = [
packages = with pkgs; [
pkg-config
rustToolchain
wasm-bindgen-cli
pkgs.binaryen
pkgs.brotli
pkgs.just
pkgs.watchexec
trunk
];
buildInputs = runtimeDeps;
shellHook = ''
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.lib.makeLibraryPath runtimeDeps}"
'';
};
};
};

View file

@ -1,35 +0,0 @@
# List available recipes
default:
@just --list
# Build the Bevy app to WASM (release by default; use `just build dev` for debug)
build profile="release":
./build-wasm.sh {{profile}}
# Build WASM in debug mode
build-dev:
./build-wasm.sh dev
# Build the HTTP server (release)
build-server:
cargo build --release -p server
# Build WASM + server for production
build-all: build build-server
# Run the server (serves ./static on :3000)
serve:
cargo run -p server
# Build WASM then run the server
run: build-dev serve
# Type-check the workspace
check:
cargo clippy --target wasm32-unknown-unknown -p app
cargo clippy --target x86_64-unknown-linux-gnu -p server
# Remove build artifacts
clean:
rm -rf static
cargo clean

View file

@ -1,9 +0,0 @@
[package]
edition = "2024"
name = "server"
version = "0.1.0"
[dependencies]
axum = "0.8"
tokio = { version = "1", features = ["full"] }
tower-http = { version = "0.7", features = ["fs"] }

View file

@ -1,17 +0,0 @@
use axum::{Router, routing::get};
use tower_http::services::ServeDir;
#[tokio::main]
async fn main() {
let static_files = ServeDir::new("static")
.precompressed_gzip()
.precompressed_br();
let app = Router::new()
.route("/health", get(|| async { "OK" }))
.fallback_service(static_files);
println!("Listening on http://0.0.0.0:3000");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}

View file

@ -9,7 +9,7 @@ fn main() {
primary_window: Some(Window {
fit_canvas_to_parent: true,
prevent_default_event_handling: false,
canvas: Some("#bevy-canvas".into()),
canvas: Some("#bevy".into()),
..default()
}),
..default()

View file

@ -3,29 +3,14 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Personal Website</title>
<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
display: block;
}
</style>
<title>Personal website</title>
<link data-trunk rel="copy-dir" href="../assets" />
<link data-trunk rel="inline" href="style.css" />
<link data-trunk rel="rust" data-cargo-no-default-features data-wasm-opt="s" href="../" />
</head>
<body>
<canvas id="bevy-canvas"></canvas>
<script type="module">
import init from './2dscene.js';
init();
</script>
<canvas id="bevy"></canvas>
</body>
</html>

11
web/style.css Normal file
View file

@ -0,0 +1,11 @@
* {
margin: 0;
padding: 0;
border: 0;
}
html,
body {
width: 100%;
height: 100%;
}