app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 8afc336aa88c8c910f1a2477abd45bb4e854dcc3
parent fa673deaa990eb1626502f8af28d584f71404aa8
Author: triesap <tyson@radroots.org>
Date:   Fri, 20 Mar 2026 16:27:14 +0000

build: bootstrap wasm target


Diffstat:
M.gitignore | 3+++
MCONTRIBUTING.md | 28++++++++++++++++++++++++++++
MCargo.lock | 28++++++++++++++++++++++++++++
MCargo.toml | 6+++++-
Acrates/app-web/Cargo.toml | 28++++++++++++++++++++++++++++
Acrates/app-web/Trunk.toml | 3+++
Acrates/app-web/index.html | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrates/app-web/src/lib.rs | 44++++++++++++++++++++++++++++++++++++++++++++
Acrates/app-web/src/main.rs | 5+++++
Mcrates/app/Cargo.toml | 3+++
Acrates/app/src/lib.rs | 21+++++++++++++++++++++
Mcrates/app/src/main.rs | 19+------------------
Mrust-toolchain.toml | 1+
13 files changed, 228 insertions(+), 19 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +1,7 @@ /target/ +/.trunk/ +/crates/app-web/.trunk/ +/crates/app-web/dist/ # Local environment files .env diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md @@ -12,6 +12,13 @@ Install the Rust toolchain used by this repository: ```bash rustup toolchain install 1.92.0 +rustup target add wasm32-unknown-unknown +``` + +Install Trunk for the wasm target: + +```bash +cargo install trunk ``` Confirm your environment: @@ -19,6 +26,7 @@ Confirm your environment: ```bash cargo --version rustc --version +trunk --version ``` ## Getting Started @@ -64,6 +72,26 @@ Run the native application: cargo run -p radroots-app ``` +Check the wasm application: + +```bash +env -u NO_COLOR cargo check -p radroots-app-web --target wasm32-unknown-unknown +``` + +Build the wasm application: + +```bash +cd crates/app-web +env -u NO_COLOR trunk build +``` + +Run the wasm application: + +```bash +cd crates/app-web +env -u NO_COLOR trunk serve --open +``` + ## Contribution Guidelines - Keep changes scoped to a single coherent change. diff --git a/Cargo.lock b/Cargo.lock @@ -322,6 +322,8 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ + "serde", + "termcolor", "unicode-width", ] @@ -1992,6 +1994,18 @@ dependencies = [ ] [[package]] +name = "radroots-app-web" +version = "0.1.0" +dependencies = [ + "eframe", + "log", + "radroots-app", + "wasm-bindgen-futures", + "web-sys", + "wgpu", +] + +[[package]] name = "range-alloc" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2311,6 +2325,15 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2745,12 +2768,17 @@ dependencies = [ "cfg_aliases", "document-features", "hashbrown 0.16.1", + "js-sys", "log", + "naga", "portable-atomic", "profiling", "raw-window-handle", "smallvec", "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", "wgpu-core", "wgpu-hal", "wgpu-types", diff --git a/Cargo.toml b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ - "crates/app" + "crates/app", + "crates/app-web", ] resolver = "2" @@ -17,7 +18,10 @@ readme = "README.md" [workspace.dependencies] eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "wgpu", "wayland", "x11"] } egui = { version = "0.33.3", features = ["serde"] } +log = "0.4.28" objc2-foundation = { version = "0.3.2", default-features = false, features = ["std"] } +wasm-bindgen-futures = "0.4.50" +web-sys = { version = "0.3.91", features = ["Document", "HtmlCanvasElement", "Window"] } wgpu = { version = "27.0.1", default-features = false } [workspace.lints.rust] diff --git a/crates/app-web/Cargo.toml b/crates/app-web/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "radroots-app-web" +version.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true +description = "Rad Roots app wasm launcher" +publish = false + +[lib] +path = "src/lib.rs" +crate-type = ["cdylib", "rlib"] + +[dependencies] +eframe.workspace = true +log.workspace = true +radroots-app = { path = "../app" } +wasm-bindgen-futures.workspace = true +web-sys.workspace = true + +[target.'cfg(target_arch = "wasm32")'.dependencies] +wgpu = { workspace = true, features = ["std", "wgsl", "webgpu", "fragile-send-sync-non-atomic-wasm"] } + +[lints] +workspace = true diff --git a/crates/app-web/Trunk.toml b/crates/app-web/Trunk.toml @@ -0,0 +1,3 @@ +[build] +target = "index.html" +dist = "dist" diff --git a/crates/app-web/index.html b/crates/app-web/index.html @@ -0,0 +1,58 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <meta + name="viewport" + content="width=device-width, initial-scale=1.0, viewport-fit=cover" + /> + <title>Rad Roots</title> + <base data-trunk-public-url /> + <style> + html, + body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + background: #0e1116; + color: #f4efe1; + font-family: ui-sans-serif, system-ui, sans-serif; + } + + body { + display: grid; + place-items: center; + } + + #app-shell { + position: relative; + width: 100%; + height: 100%; + } + + #radroots_app_canvas { + width: 100%; + height: 100%; + display: block; + } + + #loading_text { + position: absolute; + inset: 0; + display: grid; + place-items: center; + letter-spacing: 0.08em; + text-transform: uppercase; + font-size: 0.75rem; + } + </style> + </head> + <body> + <div id="app-shell"> + <canvas id="radroots_app_canvas"></canvas> + <div id="loading_text">loading rad roots…</div> + </div> + <link data-trunk rel="rust" href="Cargo.toml" data-bin="radroots-app-web" /> + </body> +</html> diff --git a/crates/app-web/src/lib.rs b/crates/app-web/src/lib.rs @@ -0,0 +1,44 @@ +#![forbid(unsafe_code)] + +#[cfg(target_arch = "wasm32")] +use eframe::wasm_bindgen::JsCast as _; + +#[cfg(target_arch = "wasm32")] +pub fn launch() { + let log_level = if cfg!(debug_assertions) { + log::LevelFilter::Info + } else { + log::LevelFilter::Warn + }; + let _ = eframe::WebLogger::init(log_level); + + wasm_bindgen_futures::spawn_local(async { + let web_options = eframe::WebOptions::default(); + let window = web_sys::window().expect("window"); + let document = window.document().expect("document"); + let canvas = document + .get_element_by_id("radroots_app_canvas") + .expect("radroots_app_canvas") + .dyn_into::<web_sys::HtmlCanvasElement>() + .expect("canvas"); + + let result = eframe::WebRunner::new() + .start( + canvas, + web_options, + Box::new(|_cc| Ok(Box::new(radroots_app::RadrootsApp))), + ) + .await; + + if let Some(loading_text) = document.get_element_by_id("loading_text") { + if result.is_ok() { + loading_text.remove(); + } else { + loading_text.set_inner_html("<p>failed to start radroots app</p>"); + } + } + }); +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn launch() {} diff --git a/crates/app-web/src/main.rs b/crates/app-web/src/main.rs @@ -0,0 +1,5 @@ +#![forbid(unsafe_code)] + +fn main() { + radroots_app_web::launch(); +} diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml @@ -10,6 +10,9 @@ homepage.workspace = true description = "Rad Roots app" publish = false +[lib] +path = "src/lib.rs" + [lints] workspace = true diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs @@ -0,0 +1,21 @@ +#![forbid(unsafe_code)] + +use eframe::egui; + +pub const APP_NAME: &str = "Rad Roots"; + +#[derive(Default)] +pub struct RadrootsApp; + +impl eframe::App for RadrootsApp { + fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + egui::CentralPanel::default().show(ctx, |ui| { + ui.vertical_centered(|ui| { + ui.add_space(48.0); + ui.heading(APP_NAME); + ui.add_space(12.0); + ui.label("radroots app"); + }); + }); + } +} diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs @@ -2,8 +2,7 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use eframe::egui; - -const APP_NAME: &str = "Rad Roots"; +use radroots_app::{APP_NAME, RadrootsApp}; #[cfg(target_os = "macos")] fn set_macos_app_name() { @@ -17,22 +16,6 @@ fn set_macos_app_name() { #[cfg(not(target_os = "macos"))] fn set_macos_app_name() {} -#[derive(Default)] -struct RadrootsApp; - -impl eframe::App for RadrootsApp { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - egui::CentralPanel::default().show(ctx, |ui| { - ui.vertical_centered(|ui| { - ui.add_space(48.0); - ui.heading(APP_NAME); - ui.add_space(12.0); - ui.label("radroots app"); - }); - }); - } -} - fn main() -> eframe::Result<()> { set_macos_app_name(); diff --git a/rust-toolchain.toml b/rust-toolchain.toml @@ -1,2 +1,3 @@ [toolchain] channel = "1.92.0" +targets = ["wasm32-unknown-unknown"]