The app
Tauri and the app
What Tauri is and why it makes small desktop apps, then clone the starter, install it, and open the Chat window.
By the end of this page the Chat window opens on your computer. The whole interface is there, but it does not talk to any model yet. That is what the next pages add.
Tauri in five minutes
Tauri builds desktop apps from a web frontend and a Rust backend.
- The window is the system's own web view. WebKit on macOS, WebView2 on Windows. Electron ships its own copy of Chromium inside every app. Tauri does not, so the finished Chat app is a few megabytes.
- One codebase, several platforms. The same code builds a Mac app and a Windows installer. Tauri 2 also targets Linux, iOS, and Android, which this course does not use.
- Rust does the work that touches the machine. HTTP calls, files, and child processes run in Rust. React only draws the page.
- Commands and Channels connect the two. React calls a Rust function with
invoke("name", args). That is a command. For anything that streams, React passes a Channel, and Rust sends messages on it as they happen. Every answer in Chat arrives that way. - Nothing is allowed by default. A capability file lists what the window may do, such as opening links or a folder picker. Everything else is denied.
You do not need to know Rust for this course. The pages show the Rust parts that matter and explain them.
Install the build tools for your system
Tauri compiles a native app, so it needs your platform's C and linker tools.
On macOS, install the Xcode Command Line Tools with xcode-select --install in a terminal. You do not need the full Xcode app.
On Windows, install the Microsoft C++ Build Tools and tick Desktop development with C++ in the installer. The Tauri prerequisites page links the download. WebView2 is built into Windows 10 and 11.
Install Rust, Node.js, and pnpm
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shInstall Node.js 22.19 or newer from nodejs.org or your version manager. Then open a new terminal and install pnpm.
npm install -g pnpm
rustc -V
node -v
pnpm -vYou need Rust 1.85 or newer. This guide used Rust 1.95.0, Node 24.16.0, and pnpm 12.9.1.
Clone the starter and install the dependencies
git clone https://github.com/daveebbelaar/local-chat.git
cd local-chat
pnpm install --frozen-lockfile
cd src-tauri
cargo fetch --locked
cd ..--frozen-lockfile and --locked install exactly the versions in the lockfiles, so your build matches this guide.
Open the app
pnpm tauri devThe first run compiles about 360 crates. That takes under a minute on a fast Mac and a few minutes on a smaller machine. Later runs take seconds.
Tauri starts two programs. Vite serves the React page on port 1420. Cargo builds the Rust app, which opens a native window and loads that page. Leave it running. When you change a Rust file, it rebuilds and restarts the window by itself.
What is in the starter
| Where | What it does |
|---|---|
src/ | The whole interface in React: sidebar, composer, model picker, markdown answers, settings, and the Code mode view. |
src/api.ts | One typed function per Rust command. React never calls Ollama directly. |
src-tauri/src/store.rs | Saves conversations and settings as JSON files in the app data folder. |
src-tauri/src/main.rs | Builds the app and lists the commands React may call. |
src-tauri/tauri.conf.json | The window, the app name, and the bundle identifier com.datalumina.chat. |
src-tauri/capabilities/default.json | What the window may do: open links, open a folder picker, drag the window. |
This is the whole Rust entry point in the starter.
// Hide the extra console window on Windows release builds.
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod store;
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_dialog::init())
.invoke_handler(tauri::generate_handler![
store::list_conversations,
store::load_conversation,
store::save_conversation,
store::delete_conversation,
store::load_settings,
store::save_settings,
])
.run(tauri::generate_context!())
.expect("error while running Chat");
}generate_handler! lists the commands React may call. Right now these are only the storage commands. The app asks for models with a command called list_models, and that command does not exist yet.
Check
- The Chat window opens with a sidebar, an empty chat, and a composer.
- The model button in the composer says "No model", because nothing talks to Ollama yet.
- Open Settings, change the system prompt, and save. Restart the app. The change is still there, because
store.rsalready works.
Close the app with Cmd+Q on macOS or Alt+F4 on Windows, or leave it running for the next page.
Models, settings and speed
Call the Ollama API by hand, stream an answer line by line, change temperature, context length and thinking, compute tokens per second, and free the memory.
Connect Ollama
Copy in the Rust module that talks to Ollama, and read the four parts that matter, the request, streaming over a Channel, Stop, and the speed numbers.