Back to Blog

Rust Modules in Tauri: Organize Your Code Like a Pro! πŸ¦€

Sandy LaneSandy Lane
β€’

Video: Rust Modules in Tauri: Organize Your Code Like a Pro! πŸ¦€ by Taught by Celeste AI - AI Coding Coach

Watch full page β†’

Rust Modules in Tauri: Organize Your Code Like a Pro! πŸ¦€

As your Tauri Rust backend grows, keeping all code in a single lib.rs file becomes unwieldy. This tutorial demonstrates how to structure your code into clean, maintainable modules using Rust’s module system, improving readability and scalability for larger projects.

Code

// src-tauri/src/models.rs
// Shared data structures with public visibility
#[derive(serde::Serialize, serde::Deserialize)]
pub struct User {
  pub id: u32,
  pub name: String,
}

// src-tauri/src/commands/user_commands.rs
use crate::models::User;

pub fn get_user(id: u32) -> Option<User> {
  // Dummy implementation
  Some(User { id, name: "Alice".into() })
}

pub fn create_user(name: &str) -> User {
  User { id: 1, name: name.into() }
}

pub fn list_users() -> Vec<User> {
  vec![User { id: 1, name: "Alice".into() }]
}

// src-tauri/src/commands/file_commands.rs
use std::fs;

pub fn read_file(path: &str) -> std::io::Result<String> {
  fs::read_to_string(path)
}

pub fn write_file(path: &str, contents: &str) -> std::io::Result<()> {
  fs::write(path, contents)
}

pub fn list_files(dir: &str) -> std::io::Result<Vec<String>> {
  let entries = fs::read_dir(dir)?;
  let mut files = Vec::new();
  for entry in entries {
    let entry = entry?;
    if entry.file_type()?.is_file() {
      files.push(entry.file_name().to_string_lossy().into_owned());
    }
  }
  Ok(files)
}

// src-tauri/src/commands/mod.rs
pub mod user_commands;
pub mod file_commands;

// Re-export for easier imports
pub use user_commands::*;
pub use file_commands::*;

// src-tauri/src/lib.rs
mod models;
mod commands;

use commands::{get_user, create_user, list_users};

#[tauri::command]
fn invoke_get_user(id: u32) -> Option<models::User> {
  get_user(id)
}

#[tauri::command]
fn invoke_create_user(name: String) -> models::User {
  create_user(&name)
}

#[tauri::command]
fn invoke_list_users() -> Vec<models::User> {
  list_users()
}

fn main() {
  tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![
      invoke_get_user,
      invoke_create_user,
      invoke_list_users
    ])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Key Points

  • The mod keyword declares modules, linking files or directories as submodules.
  • Each .rs file automatically becomes a module; directories use a mod.rs to group submodules.
  • Use pub on structs, functions, and modules to control visibility across the crate.
  • pub use re-exports simplify imports by exposing submodule items at higher levels.
  • This modular pattern keeps lib.rs minimal and your codebase scalable and maintainable.