Rust workspace: Tauri 2 + Leptos 0.8 CSR + Tailwind CSS v4 + Tokio.
cf-os-app/
├── Cargo.toml # workspace: versions only
├── core/ # cfos-core — shared domain / async
├── tauri-ui/ # cfos-ui — Leptos CSR + Trunk + Tailwind
└── tauri-app/ # cfos-app — Tauri 2 desktop shell
| Crate | Path | Role |
|---|---|---|
cfos-core |
core/ |
Shared library (tokio, serde, domain) |
cfos-ui |
tauri-ui/ |
WASM frontend (Leptos CSR) |
cfos-app |
tauri-app/ |
Native host (Tauri) |
Convention: pin versions in the root Cargo.toml [workspace.dependencies]; enable features only in each member Cargo.toml.
rustup target add wasm32-unknown-unknown
cargo install trunk
cargo install tauri-cli --version "^2"
# Node.js 26+ + git (for Cloudflare OS prepare); pnpm via corepack if missingBuild machine needs Node.js 26+ (and git). The desktop app embeds a lean Cloudflare
OS runtime — no monorepo node_modules, offline at runtime (no npm/pnpm
install). make prepare on this host only (no cross-build) stages:
| Shipped in app | Not shipped |
|---|---|
prebundled worker .js (wrangler deploy --dry-run) |
monorepo source |
frontend/ SPA |
monorepo node_modules |
configs/*.json (no build.command) |
TypeScript / Vite toolchain |
vendor/ = wrangler from monorepo (materialized at prepare) |
runtime npm/pnpm/npx |
Node via Tauri externalBin sidecar (binaries/node-$TRIPLE, host copy) |
nodejs.org dist / cross-OS Node |
start-cf-os.mjs |
# Preferred
make prepare # Node 26+, clone/build cloudflare-os + lean resources
make dev # cargo tauri dev (CF OS on :8787 when resources exist)
# Equivalent without Make
node scripts/prepare-cf-os.mjs
node scripts/bundle-cf-os-runtime.mjs --skip-prepare
cd tauri-app && cargo tauri devRelease: cd tauri-app && cargo tauri build (beforeBuild runs lean bundle with --skip-prepare).
bundle-cf-os-runtime.mjs is incremental: a content fingerprint (.bundle-stamp) skips the whole
rebuild when CF OS sources / frontend dist / wrangler pin are unchanged — so repeated
cargo tauri build only re-pays when the lean runtime actually needs updating. Dry-runs and UI
generate steps run in parallel (--jobs N or CFOS_BUNDLE_JOBS; default min(CPU, 8)). Use
--force to ignore the stamp.
| Script | Role |
|---|---|
scripts/prepare-cf-os.mjs |
Require Node 26+, clone, pnpm install, pnpm build |
scripts/bundle-cf-os-runtime.mjs |
Dry-run all workers → lean resources/cf-os (cached + parallel) |
scripts/start-cf-os.mjs |
Node + vendored wrangler multi-config dev |
On launch the app copies the lean tree into app data, then spawns
node start-cf-os.mjs (Node 26+). Logs: $APP_DATA/cf-os-runtime/logs/wrangler.log.
Env: CFOS_PORT (default 8787), CFOS_NODE_BIN / CFOS_WRANGLER_JS
(optional; the desktop host sets CFOS_NODE_BIN to the externalBin sidecar).
At prepare, CFOS_NODE_BIN selects which host node to copy into
tauri-app/binaries/node-$TARGET_TRIPLE.
# Shared library
cargo test -p cfos-core
cargo check -p cfos-core
# Browser UI (Trunk on http://127.0.0.1:1420)
cd tauri-ui && trunk serve
# Desktop (starts Trunk via beforeDevCommand; also starts CF OS if resources exist)
cd tauri-app && cargo tauri dev
# Release frontend
cd tauri-ui && trunk build --release
# Bundle desktop app (requires prior prepare; beforeBuild bundles CF OS + trunk)
cd tauri-app && cargo tauri buildGenerate bundle icons from a square PNG (≥1024×1024):
cd tauri-app
cargo tauri icon ./app-icon-source.png