Customization Guide
Renaming the Project
Replace all app- prefixes with your project name. For a project named acme:
- Rename directories:
app-core→acme-core,app-adapters→acme-adapters, etc. - Update
Cargo.tomlnames and path references in all crates - Update
usestatements:app_core→acme_core, etc. - Update workspace
Cargo.tomlmembers and exclude paths - Update
tauri.conf.json:productName,identifier, windowtitle - Rename the frontend crate (
app→acme) incrates/app/Cargo.toml
Replacing the Domain
The scaffold uses an Item/Inventory domain. To replace it:
app-core/src/domain/mod.rs— ReplaceItem,ItemIdwith your domain typesapp-core/src/error.rs— ReplaceItemErrorvariants with your domain errorsapp-core/src/ports/mod.rs— ReplaceItemRepositorywith your domain trait(s)app-core/src/dto.rs— Replace request/response typesapp-adapters/src/in_memory.rs— Implement the new trait (or replace with a real adapter)app-testutils/src/fakes.rs— Write fakes for your new traitsapp-testutils/src/builders.rs— Write builders for your new domain typesapp-tauri/src/commands.rs— Rewrite Tauri commands for the new domainapp-tauri/src/state.rs— UpdateAppStatewith the new trait(s)src/types.rs(frontend) — Mirror the new DTOs with String-based fieldssrc/tauri_ipc.rs(frontend) — Update typed command wrapperssrc/components/items.rs(frontend) — Rewrite the UI for the new domain
Adding a Real Database
Replace InMemoryItemRepository with a Diesel + SQLite adapter:
- Add
dieselanddiesel_migrationsto workspace deps - Create a
SqliteItemRepositoryinapp-adapters(see rust-architecture skill's trait-patterns reference) - Wrap
SqliteConnectioninMutexforSend + Sync - Update
app-tauri/src/main.rsto create the connection and wire the new adapter - Store the database file in the Tauri app data directory (use
app.path().app_data_dir())
Adding Tauri Plugins
File Dialogs
- Add
tauri-plugin-dialog = "2"toapp-tauri/Cargo.toml - Register:
.plugin(tauri_plugin_dialog::init())inapp-tauri/src/main.rs - Add
"dialog:default","dialog:allow-open"toapp-tauri/capabilities/default.json - Use the full IPC template from the dwind-tauri skill's reference which includes
pick_fileandpick_directory
Shell (open URLs in browser)
- Add
tauri-plugin-shell = "2"toapp-tauri/Cargo.toml - Register:
.plugin(tauri_plugin_shell::init())inapp-tauri/src/main.rs - Add
"shell:allow-open"toapp-tauri/capabilities/default.json
File System Access
- Add
tauri-plugin-fs = "2"toapp-tauri/Cargo.toml - Register:
.plugin(tauri_plugin_fs::init())inapp-tauri/src/main.rs - Add appropriate
"fs:*"permissions toapp-tauri/capabilities/default.json
Asset Protocol (serve local files in webview)
- Add
features = ["protocol-asset"]to thetauridependency - Enable in
tauri.conf.json:"security": { "assetProtocol": { "enable": true, "scope": ["**"] } } - Use
tauri_ipc::convert_file_src(path)to convert paths toasset://URLs
Adding Backend Events
The backend can stream events to the frontend:
#![allow(unused)] fn main() { // Backend (commands.rs) #[tauri::command] pub async fn long_operation(app: tauri::AppHandle) -> Result<(), String> { app.emit("progress", 50).map_err(|e| e.to_string())?; // ... app.emit("progress", 100).map_err(|e| e.to_string())?; Ok(()) } }
#![allow(unused)] fn main() { // Frontend (lib.rs) tauri_ipc::listen::<u32>("progress", move |percent| { progress_state.set(percent); }); }
Adding More Tauri Commands
- Add the
#[tauri::command]function inapp-tauri/src/commands.rs - Register it in
generate_handler![...]inapp-tauri/src/main.rs - Add a typed wrapper in
src/tauri_ipc.rsusinginvokeorinvoke_unit - Call from the frontend component