Sitemap

Build a WebAssembly Ready App in Rust (2025): Mini Project for Beginners🦀

4 min readAug 5, 2025

--

Part of series: Rust Tutorial for Beginners: Learn the Rust Programming Language from Scratch and Build a WebAssembly Ready App (Article Series)

So far, you’ve picked up the basics of Rust — variables, functions, control flow, structs, enums, ownership. Now it’s time to bring all that together.

You can switch to video version of Rust Crash Course to the relevant chapter

Learn Rust from scratch in just 1 hour — perfect for beginners in 2025 - LearnAwesome— YouTube

In this article, we’ll walk through building a real-world Rust project from scratch: a reusable math library with a command-line interface (CLI) frontend. Along the way, you’ll learn how to structure your code with modules, separate logic cleanly, and even prepare for future WebAssembly (wasm) use..

Note we are NOT going to cover webassembly integration in this article. This series is about Rust programming language. You can refer to our Webassembly Rust Tutorial Video to learn how to do so.

You can switch to video version of Rust Crash Course to the relevant chapter

🔧 While we won’t compile it to Wasm in this part, the way we structure the app makes it portable for a follow-up where we’ll cover full WebAssembly deployment.

Let’s dive in.

🛠️ Step 1 — Create the Project

Let’s begin by creating a new binary Rust project:

cargo new rust_math_lib --bin
cd rust_math_lib
touch src/lib.rs

Using --bin creates an executable project with main.rs as the entry point — ideal for our CLI. We’ll also create a lib.rs, where the reusable logic will live.

🗂️ Step 2 — Create the Math Module

Inside src, let’s organize our math functionality into a dedicated folder:

mkdir src/math
touch src/math/mod.rs
touch src/math/operations.rs

Then update src/lib.rs to declare the math module:

pub mod math;

In src/math/mod.rs, wire in the operations submodule:

pub mod operations;

Now, implement your math logic in src/math/operations.rs:

pub fn add(a: f64, b: f64) -> f64 {
a + b
}
pub fn subtract(a: f64, b: f64) -> f64 {
a - b
}
pub fn multiply(a: f64, b: f64) -> f64 {
a * b
}
pub fn divide(a: f64, b: f64) -> Option<f64> {
if b == 0.0 {
None
} else {
Some(a / b)
}
}

These functions are intentionally simple — they focus on pure logic with no I/O, making them reusable and testable.

🧠 lib.rs is the gateway to your library code — it exposes modules like math::operations so other parts of the project (or external tools like WebAssembly) can use them.

❓ Why use Option<f64> instead of Result<f64, String>?

Since we’re targeting both CLI and WebAssembly, returning Result with string errors would add unnecessary complexity in wasm contexts. Option is simpler and works cleanly in both environments: Some(value) for success, None for errors like division by zero.

💻 Step 3 — Build the CLI in main.rs

With the library in place, let’s write a CLI app in src/main.rs to use it:

use std::io;
use rust_math_lib::math::operations;
fn main() {
println!("Welcome to Rust Math CLI");
println!("Choose an operation: add, subtract, multiply, divide");
let mut operation = String::new();
io::stdin().read_line(&mut operation).unwrap();
let operation = operation.trim();
let mut input1 = String::new();
let mut input2 = String::new();
println!("Enter first number:");
io::stdin().read_line(&mut input1).unwrap();
println!("Enter second number:");
io::stdin().read_line(&mut input2).unwrap();
let a: f64 = input1.trim().parse().unwrap();
let b: f64 = input2.trim().parse().unwrap();
let result = match operation {
"add" => Some(operations::add(a, b)),
"subtract" => Some(operations::subtract(a, b)),
"multiply" => Some(operations::multiply(a, b)),
"divide" => operations::divide(a, b),
_ => {
println!("Unknown operation");
None
}
};
match result {
Some(r) => println!("Result: {}", r),
None => println!("Could not compute result (maybe division by zero?)"),
}
}

This CLI uses basic input/output and pattern matching — no external dependencies needed.

✅ Step 4 — Test It Out

Build and run your CLI:

cargo run

Try each operation — including dividing by zero — and you’ll see how your CLI handles it with clean, readable Rust code.

🌐 Step 5 — Why This Is WebAssembly-Ready

So far, we’ve been using this app in the terminal. But here’s the exciting part: this exact library can be compiled to WebAssembly and run in the browser.

🧠 WebAssembly (wasm) allows high-performance languages like Rust to run safely inside modern browsers — right alongside JavaScript.

Because our logic is separated into a lib.rs and math/operations.rs, and doesn't rely on stdin/stdout, it's already wasm-compatible.

Get Ali Aslam’s stories in your inbox

Join Medium for free to get updates from this writer.

You don’t need to rewrite anything. The same functions used by the CLI can be exposed to JavaScript with minimal setup.

💡 If you’ve seen our “Rust + WebAssembly: Hello World” video, you already know the basics of setting up wasm-pack, exporting functions with #[wasm_bindgen], and calling Rust code from JS.

We’ll cover this exact library’s wasm conversion in a future tutorial — but if you’re curious, you’re already 90% there.

And again, our use of Option<f64> instead of Result<f64, String> avoids wasm’s string-handling complexities.

🧠 Summary

You just built a modular Rust app that:

  • ✅ Organizes reusable logic in a clean folder structure
  • ✅ Runs in the terminal as a simple CLI tool
  • ✅ Is ready to be reused in WebAssembly — or published as a crate

🎯 “Mini projects like this are perfect to reinforce concepts. They give you confidence while preparing for real-world development.”

Next up: Crates, External Libraries, and Cargo Ecosystem ➡️

Press enter or click to view image in full size

--

--

Ali Aslam
Ali Aslam

Written by Ali Aslam

Avid Learner | Principal Software Engineer | Full Stack Developer