Rust + Tauri + Svelte Tutorial

Rust Tauri

Intro

As Rust is getting more traction and more people want to learn it, I've decided to create another tutorial mainly for beginners. There are few ways to create desktop applications using Rust and Tauri is definitely one that will allow you to make beautiful UI (HTML/JS/CSS) and leverage power of Rust in the background. As Tauri lets you choose any frontend framework (or none) I've created a simple template that use Svelte and Bootstrap (through Sveltestrap) to give developers a nice starting point. To demonstrate how to use it we will create simple password generator.

If lost, here you can find finished project: https://github.com/jbarszczewski/pass-gen-tutorial

Let's start!

Create project

Ok this step is super simple. All you have to do is run this command:
degit jbarszczewski/tauri-svelte-template pass-gen-tutorial

Alternatively you can go to https://github.com/jbarszczewski/tauri-svelte-template and click Use this template button.

Quick overview of the project:

  • /src contains front-end code with the main view defined in App.svelte file.
  • /src-tauri here lives 'back-end' Rust code.
  • README.md provides basic instructions how to work with Tauri.

Add Rust command

Ok we want to create a simple command that will accept password length and return random string.
We will require one package to be added, rand, that generates random numbers. Open src-tauri/Cargo.toml and add rand = "0.8.0" under dependencies. At this point run yarn and thenyarn tauri dev command (from the project main directory) to view the changes in 'real-time'.

Note: First build might take a while as it's building project from scratch.

Now open /src-tauri/src/commands.rs file and replace the existing content with the following:

use rand::Rng;

static CHARS: [char; 70] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's','t', 'u', 'v', 'w', 'x', 'y', 'z','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S','T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!','@','#','$','%','^','&','*'];

#[tauri::command]
fn generate_password(length: u32) -> String{
    let mut rng = rand::thread_rng();
    let mut result = String::new();
    for _x in 0..length {
        result.push(CHARS[rng.gen_range(0..70)]);
    }

    result
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn generates_string() {
        let result = generate_password(8);
        assert_eq!(result.len(), 8);
    }
}

Now let's look what this code does:

  1. Import rand package.
  2. Create array with characters that can be used for password generation.
  3. Define new Tauri command generate_password that accepts password length as an integer.
  4. Create new random generator and an empty string.
  5. In the 'for' loop fill the string with characters from CHARS array
  6. Return string containing password.

Additionally we have a single test that checks if newly created password have proper length (run cargo test from /src-tauri directory). Of course there is a room for improvement, like adding options to select types of characters to be used (only lowercase, no symbols etc.) and expand tests for better coverage. But as mentioned at the beginning this is just a simple app to demonstrate the template.

Last thing to do is rename command imported in main.rs to generate_password rather than standard my_custom_command and Rust code is ready to be used!

Modify Svelte component

We need to modify the front-end Svelte component to call our new command. Changes here are actually simple: we want to modify input to be a slider and pass it's value as a string to invoked command (remember we've changed the default name). Open App.svelte and let's start adding those changes.

In <script> section replace code after imports with following one:

let input: string = '8';
let result: string = '';
const handleClick = async () => {
    result = await invoke('generate_password', {
        length: +input,
    });
};

Difference are:

  • Default value for input
  • Command and parameter names with casting string to number: +input

The <main> tag will also look very similar, we update texts and change input to be a range type:

<Container>
    <Card class="mb-3">
        <CardHeader>
            <CardTitle>Password Generator</CardTitle>
        </CardHeader>
        <CardBody>
            <CardSubtitle>Generate random password</CardSubtitle>
            <CardText>Press 'Generate' button to create password with length: {input}.</CardText>
            <input
                type="range"
                id="exampleRange"
                bind:value="{input}"
                min="{1}"
                max="{32}"
                step="{1}"
            />
            <button color="primary" on:click="{handleClick}">Generate</button>
        </CardBody>
        <CardFooter> {#if result.length !== 0} {result} {:else} No result yet. {/if} </CardFooter>
    </Card>
</Container>

And we're done! Congratulations, you've just created your first Tauri app!

Conclusion

As you can see, it's really easy to create application with nice UI leveraging power of Rust in the background. There is a lot more good stuff in Tauri, like: updater if you plan to distribute your app and make sure users don't miss newest releases, splashscreen if app needs some time to load, etc. I really recommend heading to Tauri Docs to learn more about all the possibilities.

The complete project can be found here https://github.com/jbarszczewski/pass-gen-tutorial

I hope you've enjoyed this tutorial and as always if any suggestions/questions don't hesitate to leave a comment below.

Thanks for reading and till the next time!

82