How I Built My First Desktop App with Tauri - Tutorial
I have always wanted to develop a desktop app and I have been searching for an easier way that I can leverage my Javascript skills to create such app without learning new programming languages like .NET.
My idea for the App was to create a break reminder app with sound notifications to remind me to take regular breaks when working. While focus mode can do this, it does not have sound reminder and recommendations for activities to undertake during the break, such as drinking water and stretching. The only app that I found that solved this problem was Motion Minute, which is a paid app.
I began by creating a web version and made it installable with similar functionalities. Check it out at Pulse Break. This web version can be installed as progressive web app, which means that it runs on the browser. However, my main issue was that if I closed the browser tab, the app could not remain running on the background. I wanted an App that could be minimized to the system tray to minimize distractions.
I researched on ideas on how to pull this off and the suggestions were to use electron since it would allow me to build a native app that runs on chromium. However, the main problem with electron is that it is bloated and eats way too much RAM. This is when I discovered Tauri, which is a new kid in the block.
What is Tauri
Tauri is a framework for building tiny, fast binaries for all major desktop and mobile platforms. Developers can integrate any frontend framework that compiles to HTML, JavaScript, and CSS for building their user experience while leveraging languages such as Rust, Swift, and Kotlin for backend logic when needed.
Tauri is rust based that is composed of two modules: the client-side module in standard Web technologies (HTML, Javascript, and CSS) and the backend module in Rust. Instead of bundling a browser, Tauri renders the UI using the host operating system's native WebView. This makes Tauri lightweight and allows it to run on both MacOS, Windows and Linux, with options for even Android devices.
Getting Started with Tauri
You can read more on Tauri documentation on their official site What is Tauri? | Tauri. However, I did not find the documentation that easy to understand so I am going to make it straightforward.
Get started building with create-tauri-app by using one of the below commands. Be sure to follow the prerequisites guide to install all of the dependencies required by Tauri. For a more detailed walk through, see Create a Project.
This will create a new project with prompts on the name of the app, and the framework like Javascript or Typescript. You can also use React, Vite or just Vanilla Javascript. However, before you run this code, you need to install the prerequisites first.
Prerequisites
To run tauri, you need to install Node Js, Rust and Visual Studio Build Tools 2022 for Windows to allow you to compile C++ code. You can check more details about the required apps on the official page: Prerequisites | Tauri.
Folder Structure
For my app. I decided to go with just Vanilla Javascript since I already had the full code for everything. The folder structure for a plain Javascript is very simple, with sub-folders for the client and the server.
The Tauri project structure is split into two primary environments: the root directory, which acts as a standard web workspace containing your package.json and a src/ folder for your frontend assets (HTML, CSS, and Vanilla JavaScript), and the src-tauri/ directory, which houses a fully self-contained Rust project. While the frontend lives in src/ and handles the user interface, the src-tauri/ folder manages the application's lifecycle, system permissions via tauri.conf.json, and native logic within its own Rust-based src/ directory. This clean separation ensures that your UI remains decoupled from the low-level system code, allowing you to swap web frameworks or update native functionalities without interfering with the opposing module.
Start Development Server
After creating the App, you can use the CLI to install all required dependencies and run your app.
To change the app icons, add favicons to the project src folder. I added my icons in a public folder located in the src folder for the client. Tauri will autogenerate app icons for you based on your images. Run this command to generate the icons.
In this case, I was generating icons based on my png saved as android-chrome-512x512. The second change that I made was to replace the html, css and js files with the code i had previously written for my app. You can check the repository here: Donvine254/pulse-break.
Rust exposes various APIs that you can import into your project. However, the main entry is the Invoke function that allows your javascript code to interact with your Rust backend.
Another file that I edited was Rust. Although I do not know how to write Rust code, I had some help from Claude Code. The changes allowed me to add other native functionalities like minimizing to the taskbar when the app is closed, and invoking windows notifications.
This code configures a Tauri system tray application with a toggleable "Mute" state and custom menu interactions, utilizing Rust's strict ownership model to safely manage data across different asynchronous events. The use of Arc (Atomically Reference Counted) and the .clone() method is essential because Rust’s move closures take full ownership of the variables they capture; without cloning the mute_state and mute_i menu item, the first closure would "consume" these variables, making them inaccessible to the rest of the application. By creating clones, you are incrementing a reference counter that allows the tray's event handler to share access to the same thread-safe atomic boolean and UI elements, ensuring the backend can update the menu text and toggle global states even as the application runs in the background.
Building Your App
The last step to build a production build that can be installed. This is done by running:
This generates a native installer (.msi for Windows, .dmg for Mac, .deb for Linux) inside src-tauri/target/release/bundle/. These installers are incredibly small because, as we discussed, they don't bundle a whole browser!
Congratulations, you have now built a native app for yourself. Now go show it off to your friends.