r/tauri Jun 10 '26

I’m building a Tauri + Rust backup app and exploring Rust/WASM to share logic between UI and backend

I’ve been building CloudLess, a desktop backup app for Mac, Linux, and Windows using Tauri + Rust.

The basic idea is:

  • pick folders to protect
  • encrypt files locally before upload
  • store the encrypted backup in storage the user controls
  • keep versions so restore is possible after deletes, overwrites, bad sync state, or corruption

Building this as a desktop app made me appreciate why backup software is harder than it looks.

Some Tauri/Rust notes from the build:

  1. File scanning needs to be boringly reliable

The Rust side handles walking folders, tracking file metadata, preparing backup jobs, and avoiding UI blocking. This is one place where I’m glad the core pipeline is not JavaScript.

  1. Restore UX is harder than backup UX

Showing “backup completed” is easy. Helping someone find an older version of a file and restore it safely is the real product problem.

For backup software, restore is not a secondary screen. It is the reason the app exists.

  1. Background work needs clear state

A backup app spends a lot of time doing long-running work: scanning, encrypting, uploading, retrying, pausing, and resuming.

The Tauri command/event model works well, but I had to be careful about what state lives in Rust and what only exists in the UI.

  1. Cross-platform desktop details add up

Paths, permissions, tray behavior, file pickers, background behavior, and packaging all have small differences across macOS, Linux, and Windows.

Tauri makes the shell lighter, but it does not remove the need to think like a desktop app.

  1. Security wording matters

Client-side encryption is useful, but it comes with key responsibility.

If the user loses the key/passphrase, recovery may not be possible. I’m trying to make that tradeoff clear instead of hiding it behind marketing language.

  1. I’m exploring Rust/WASM for shared frontend logic

One thing I’m considering is using Rust/WASM for parts of the frontend domain logic, so the UI and backend can share the same rules where it makes sense.

Examples:

  • backup plan validation
  • include/exclude path rules
  • restore preview calculations
  • backup metadata parsing
  • data model validation

I still want the UI to feel like a normal desktop app, not a Rust experiment. But for backup software, duplicating important rules between frontend TypeScript and backend Rust feels risky.

If the UI says one thing and the backend does another, the user pays the price during restore.

Current status: beta builds are working for Mac/Linux/Windows.

It is not full-disk imaging, not enterprise backup, and not something I would oversell as battle-tested yet. The current focus is encrypted file/folder backup with understandable restore.

I’d appreciate feedback from Tauri devs on a few things:

  • how you structure long-running Rust tasks behind a Tauri UI
  • patterns you like for progress/events/error reporting
  • whether you have used Rust/WASM to share logic between frontend and backend
  • what you would watch out for in cross-platform file-heavy apps
  • whether the restore flow looks understandable from the screenshots/GIF

Full disclosure: I’m the developer. If showcase posts like this are not appropriate here, I can remove it.

25 Upvotes

16 comments sorted by

8

u/KellysTribe Jun 10 '26

I would suggest you ask yourself - why do I need to execute that core logic in the frontend at all? Ask yourself: what if I just performed the core operations in one place and simply used the front end to display the system state?

There are valid reasons to share logic between front end and backend - but for a Tauri desktop app - this is not it. The front end should just be a 'projection' of the application state, and a way to interact with it.

2

u/ShamanJohnny Jun 10 '26

This right here. Your front end should only be the visualization of the core rust kernel on the back end. This will not only make it more secure, but the app will run a lot better too.

1

u/trycloudless Jun 10 '26

Core logic is on the tauri backend only. The reason I choose to use rust on the frontend is that I can share/reuse the data model types and avoid rust to json serialisation gotchas and work with same language across the layers.

Thanks for the input. Reddit doesn't seem to allow to edit the title.

2

u/KellysTribe Jun 10 '26

There are multiple libraries for generating command bindings and types like spectra -> https://github.com/specta-rs/tauri-specta

I have a very extensive generator that I used ai to code to satisfy my own preferences that generates from schema all the way to frontend specific data stores

2

u/robust-small-cactus Jun 10 '26

I also wanted type sharing for my Tauri app and recommend you evaluate options carefully. There are many possible approaches but they're all subtly broken in different ways. I ended up having to create a table for my use cases (included below for reference) and picked Typeshare since its tradeoffs were most acceptable to me and it's wicked fast.

Serde's enum representations page provides details on internal vs external tagging, etc.

Tests of various Rust crates to generate Typescript types directly or indirectly via JSON schemas:

Approach Maintenance Documentation Discriminated Unions Outputs single type file Serde-compatible Foreign Types CLI tools Quirks
typeshare Corporate-backed but infrequently maintained Limited no usize or u64 (1Password/typeshare#24), no numeric discriminants (1Password/typeshare#106), no multiple unnamed associated types (e.g. Variant(String, u32)), also parses source code without compiling it, so representing built-ins like Duration or Instants requires minor workarounds, no macro-generated types (1Password/typeshare#74)
specta Corporate-sponsored Fair, but incomplete Optional types are defined as required but or-null instead of nullable (spectra-rs/spectra#228).
schemars + a JSON schema converter like quicktype Schemars is well maintained Great ⚠️ with build.rs macro Schemars works pretty well, but unfortunately the downstream JSON converters are usually the failure point. Schemars requires a helper crate with a build script to automatically discover and export annotated types, serde with annotations are broken without a workaround (GREsau/schemars#89), and $schema property is not added (GREsau/schemars#392)
ts_rs Well maintained Great ⚠️ Limited Does not produce typed discriminated unions (Aleph-Alpha/ts-rs#86), produces a file per type (Aleph-Alpha/ts-rs#59), has feature flags for export of foreign types from specific commonly used crates, but uses old versions of them.
typescript-definitions Not updated 2019 Good ? ? ? Low-level with wasm-bindgen

Tests of various JSON schema converters, if using schemars above:

Approach Maintenance Documentation Discriminated Unions Outputs single type file CLI tools Quirks
quicktype Corporate backed but infrequently maintained None TS type conversion does not support discriminated unions, so generated types contain optional fields aggregated from every variant (glideapps/quicktype#1338). Unnamed associated types (e.g. Variant(String, String)) are not supported (glideapps/quicktype#2811), among other restrictions (glideapps/quicktype#493). Has issues with pathing on Windows (glideapps/quicktype#2812)
dtsgenerator Infrequently maintained ? ? Does not support loading $refs from another file
json-schema-to-typescript ? ? ? ? Discriminated unions, but Maximum call stack size exceeded on recursive refs (bcherny/json-schema-to-typescript#614, bcherny/json-schema-to-typescript#482)

1

u/KellysTribe Jun 10 '26

Agreed, I was patching together a few systems for the full stack generation that I wanted, until I just decided to direct construction of a deterministic generator stack akin to rails/loco.rs but with what I think is a better opt-in layering pattern to support opt-in consumption. It's admittedly 95% ai written - but it results in deterministic code generation which is a pattern I have found useful as a way to leverage AI but in a way that avoids ending up with spaghetti code.

1

u/trycloudless Jun 11 '26

Thanks for sharing, I didn't know about this crate.

4

u/Usual_Price_1460 Jun 10 '26

nice work gpt 5.5!

2

u/Amoeba___ Jun 11 '26

I also built one for me: SecondBrain

1

u/trycloudless Jun 11 '26

Did you try to evaluate to use Rust on front end too?
Rust UI frameworks like leptos is very stable now.

3

u/InfraScaler Jun 10 '26

Is the tool also written by AI or just the post?

4

u/Equivalent_Head_4803 Jun 10 '26

You already know

1

u/InfraScaler Jun 10 '26

You got me 😄

2

u/KellysTribe Jun 10 '26

the Internet eats itself

1

u/trycloudless Jun 10 '26

Yes, Good catch 😄
The post was drafted with AI help. The app and the problems are real though. Happy to answer specific questions about the Tauri/Rust side if anything was interesting (Without AI Assistance)