The Unlikely Friendship Between React and Rust

Rate this content
Bookmark
26 min
20 Oct, 2023

Comments

Sign in or register to post your comment.

AI Generated Video Summary

This Talk explores the unlikely friendship between React and Rust, showcasing how they can be used together. The speaker demonstrates live coding and explains the process of calling Rust functions from JavaScript using the Tauri framework. The Talk also covers retrieving system information and disk details using Rust's sysinfo library. The speaker emphasizes the importance of serializability and showcases a button and SD card reader as examples of practical applications.

1. Obsession with Airports

Short description:

I'm weirdly obsessed with airports. I thought the same about airports. That's not true because then I went to Luton and my life changed for the worst.

So, let's dive in. Okay, so I don't actually have to do anything on the computer so we can just — yeah, there we go. That's my mouse, as you can see, and I want to say that I am — I'm not an expert in obsessed with airports. I'm weirdly obsessed with airports. I'm still waiting for people, so I'm just going to talk about airports for, like, a minute. So, like, I know there are some people here from Portugal and when you're from Portugal, you kind of assume that everything your country does is kind of, like, below average of other EU countries, so I thought the same about airports. That's not true because then I went to Luton and my life changed for the worst. It was like a realisation moment. I thought, oh, Portugal isn't that bad. I mean, I still left, but sure.

2. The Unlikely Friendship between React and Rust

Short description:

I'm going to be talking about the unlikely friendship between React and Rust. My name is Sarah and I'm a founding engineer at Axo.dev. We do development tools mostly for the Rust community. Rust isn't that bad. If something builds, then it's most likely gonna work. I am here to make you look at Rust code and be like... What the fuck? We're gonna talk about Tari, a native app builder that doesn't use JavaScript in the backend.

Okay. Give me some time for people to come in. But, yeah. So, I'm going to be talking about the unlikely friendship between React and Rust.

So about six months ago, let me just introduce myself. So my name is Sarah, or Sarah, but if you call me Sara, I will answer you in Portuguese and you'll have no idea what's happening so please call me Sarah. That confuses my brain. My name is Sarah and I'm, again, originally from Portugal. I'm a founding engineer at Axo.dev. Axo.dev is a very small company. We are fully... I forgot my phone. Nathaniel, can you bring me my phone? Nathaniel is not there. Sir? Can I get my phone? I need my cheat! I was trying to be an adult and be like, I'm not taking my phone to a talk.

Okay. So, we both... We basically do a lot of like... I mean, you can... If my mom asks, I say I work on computers. I say we do development tools mostly for the Rust community. So, I've been doing Rust. And Rust isn't that bad. Like, I'm not gonna say that it's easy. But you get used to it. You get used to how good it is in terms of... If something builds, then it's most likely gonna work. And that's nice. Right? That is very nice.

So, what is my purpose here today? I am here to make you look at Rust code. I'm here to make you look at it and be like... What the fuck? And be like... Oh, so that's how she fell when she went to Luton. Yeah, that's how I fell when I went to Luton. I have not gone back to Luton. I refuse to go back to Luton. I know there's a tram now, and you don't have to take the bus. I don't care. I will not go back to Luton. Okay. So, we're gonna talk about Tari.

Okay. I can't see anyone, so I'm gonna ask you to make some noise if you've heard of Tari. Okay. I have no idea how much percentage that is. So I'm still gonna talk about it. So, Tari is... So, everyone knows Electron. Tari is the same idea. You can build native apps, but instead of using JavaScript in the backend, like an animal... I'm kidding.

3. Rust, JavaScript, and Live Coding

Short description:

Rust is fast and has good integration with the OS. There's a bigger overlap between JavaScript and Rust than you may think. Last week, I was emceeing at Eurorust and there was a React conference in Brussels at the same time. Now, let's move on to live coding where we'll create a small app to display system information.

You use Rust. So, what is nice about it is that, first of all, Rust is fast. But also, Rust has a really good integration with your OS, because Rust is a systems-level language. So, you know what that means. But the point is, it's nice.

Also... Oh, shit, I forgot to make the joke. Thank you all for being here on this beautiful day, the day that Super Mario Wonder comes out. And apparently also Spider-Man. Which is the new Barbie Oppenheimer discussion. Also, there's a bigger overlap between JavaScript and Rust than you may think of. Also, actually, last week, I was emceeing at Eurorust. I will not do talks about Rust, because they will correct me. But I was emceeing at Eurorust, because a lot of my company people were there. And it's not my company. A lot of people from the company I work in were there. And at the same exact day, there was a React conference. In Brussels. I've never even been to Brussels. It's not like the place where everyone goes. It's not London. It's not Paris. Like, how many people have gone to Brussels? And if you're from Belgium, that doesn't count. See, I saw one hand. No one goes to Brussels. But there were two conferences at the exact same time. Because they thought, the JavaScript ones, thought there wouldn't be an overlap. And it turns out that a lot of people who do Rust came from JavaScript. Which is interesting. I don't know what it means, but it's interesting. Okay.

So now we're gonna be live coding. Because I don't like listening to my own voice for 20 minutes. So we're gonna do some live coding. And basically we're gonna make a small... This is my talk.md. There we go. We're gonna make a small app that tells you some system information from my computer. Yeah. I mean, that's about it. So I have pretty bare-bones Tari app here. I've downloaded a couple of packages for the frontend. I've downloaded mostly... The thing that's important that I downloaded was... For the frontend, I downloaded Mantine UI so that you don't have to look at me writing CSS, and shit, stuff doesn't look like crap. And I made some components so that stuff doesn't look like crap. So that it sounds more incredible. And they're like, oh shit, she did that on stage. Yeah. I've also downloaded Serde.

4. Downloading Sysinfo-rs and Serde

Short description:

I downloaded two things: Sysinfo-rs and Serde. Serde is like JSON.parse with superpowers and types that will kill you. Rust doesn't have any like TypeScript. The two files I need are in the source and sourced Tauri folders.

That's for the Rust part. I downloaded two things. Sysinfo-rs, which gets info from your computer, and Serde. One easy way to explain Serde is if JSON.parse had superpowers and you could type it. That's Serde, basically. Just imagine everything you have in JavaScript, but with types. But not like TypeScript types. Like, types that will kill you. TypeScript... There's no any in Rust. You want an any? No. No, seriously. It's very painful. And sometimes it's very painful. I think there are some cursed ways to do it.

So, as you can see or you can't see... Wait. How is the... Should I put it bigger? Thanks. Okay. Should I put a light theme to scare everyone? Wait. Let's go. Color theme... Night owl light. There we go. I'm not doing this. I don't hate myself. This much. I have self-esteem issues. But they're not that big.

Okay. The only two files that I really need are these two. So I can actually do this. Beautiful. And... There we go. I was in Belgium. They speak French. In that part. Please don't correct me. I know they speak Dutch as well. Okay. So... We have... I actually need to show you the folders. We have mostly two folders. We have a source and we have a sourced Tauri. Which means the source is your JavaScript and the sourced Tauri is what? Your Tauri files. Which are Rust files. Rust files and NRS.

5. Installing Rust Extension and Running the App

Short description:

Install the Rust extension for VS Code. So let's start up this app. Run Yarn Tari Dev. It will run your dev server on Tari. Now it says hello, React Advanced. We have a function called getInfo that returns a string saying hello from Rust. But how do we return this? Also, strings are painful in Rust.

Install the Rust extension for VS Code. Otherwise your life will never... Just please... For the love of God. For everything. It's the one that tells you all of this stuff. What are the types that come back and all that kind of stuff. So if you're gonna use Rust, please do that. And yeah.

So let's start up this app. So I'm just gonna run... That is small. And that doesn't do anything. You know what? I'm just gonna run... I don't need this for anything else. That's it. That's really it. What does that say? Okay. So run Yarn Tari Dev. Starts your... Yes, does Yarn Dev? Or npm run Tari? I don't care. The point is, it runs... Ignore these warnings. I know they're there. It's all a plan. It will come up in the end. Yarn Tari Dev will run your dev server on Tari. So the Rust part and the JavaScript part. Cool! So where the hell is my thing? There we go. Okay, cool. So now it says, hello, React Advanced. We've done an app! That was the pause for the clapping that no one did. Thank you. Wow, Jesus Christ. You all came from Luton, I see. Okay, so it also... Sorry. My brain went to the... There was a guy that made a welcome to Luton sign, and put it in an empty field near earthrow, and I just thought of that. That guy's a fucking hero. I don't think I can curse in GitNation conferences, and I forgot that. So that says hello React Advanced. That's not very impressive because that's here. We all can do this bit of React. Okay, but I have a function here which is getInfo, which will return our info, I promise. And that says, that returns a string that says hello from Rust, and that is the thing that we actually should be returning, right? But we're not. And how do you actually call this? Oh, also, one important thing, main.rs is the same thing as index.js. You can think about it that way. So Rust will look for main.rs. So how do we return this? Also, why the hell do I have to write string from? Okay, if you're going to do Rust, you need to know that strings are painful.

6. Calling Rust Functions with Invoke

Short description:

We'll get to that part in a part that's actually kind of just absurd, but strings in Rust are painful. So how do we call this? We make a use effect. This is all in honor of Super Mario Wonder. Okay, so I'm going to create a use effect. And I'm going to create a function called get info. So how do we actually call Rust functions? There is a thing called invoke that comes from Tory that you can use to call Rust functions. Let's first create some state. So const info set info equals use state. And then what I want to do is say okay, so const a whatever await invoke. And I'm going to say okay invoke system info. And let's console.log. Oh, I call it i for some reason. Let's return info which we're not using. And get info here. That sounds about right. Let me call get info here. Let me now run this every time everything changes. Oh, there's another difference. It uses Firefox under the hood instead of Chrome. And now I actually need to call it here. So const info equals it's like this. Info. Equals use info.

We'll get to that part in a part that's actually kind of just absurd, but strings in Rust are painful. There are like four types of strings, and yeah, that's it. Also, writing this is the same thing as writing this. If your last line does not have a semicolon, Rust assumes you're returning it.

So how do we call this? We make a use effect. This is all in honor of Super Mario Wonder. All of these voices. Okay, so I'm going to create a use effect. Why am I going to create a hook? Because that's how you hide your shame. Const use info. There we go. And I want to call a use effect on the start of it. And I'm going to create a function called get info. So const get info equals. And this needs to be async. There we go. Okay, cool. So how do we actually call Rust functions? And why is there an error in my Rust function? Oh, because I left this. Okay, cool. Okay, how do I actually call Rust functions? So there is a thing called invoke that comes from Tory that you can use to call Rust functions. So all invokes are by default async. So that's why this is async.

So let's first of all create some state. So const info set info equals use state. There we go. And then what I want to do is say okay so const a whatever await invoke. So I can import invoke from Tory apps API. And then there is no autocomplete, actually. So I'm just going to have to come here and see what is the name of the function that I exported. And you can see that by it says Tory command. So that means that it's a command that I can call in JavaScript. And I'm going to say okay invoke system info. And let's console.log. Oh, I call it i for some reason. Let's return info which we're not using. And get info here. That sounds about right. So let me call get info here. And let me now run this every time everything changes. That was not it. How did I do that? That was impressive. Cool. So. Oh, there's another difference. It uses Firefox under the hood instead of Chrome. So. And now I actually need to call it here. So const info equals it's like this. Info. Equals use info.

7. Returning System Info

Short description:

Did I call it use info? I did. And we get a low from rust. That's cool. Should I return this? Probably. Just ignore all the errors, because I have no idea what they are, and we're not talking about them now. I have a purpose, and I'm finishing this.

Did I call it use info? I did. Look at that. Coming up with the same names. And we get a low from rust. That's cool. Should I return this? Probably. Okay. So I'm going to do set info equals I. And then I can just do this. So instead of saying a low React advance, I don't know why I put two. I apologize. How dare I? There's still two on this side. Oh, my God. And now it says a low from rust. Okay. Cool. Just ignore all the errors, because I have no idea what they are, and we're not talking about them now. I have a purpose, and I'm finishing this. Okay.

8. Serializing Data in Tari: A Practical Guide

Short description:

Everything that comes out of Tari to JavaScript must be serializable. Serdai allows you to create serializable stuff. We want to return system info, which includes the name, kernel version, OS version, and host name. To specify the return type, we use 'system info'. We need to invoke 'sysinfo' to get the system info.

So there is one thing that is very important to know about Tari. Is that everything that comes out of Tari to JavaScript must be serializable. And what I mean by serializable is that you can JSON that parse it, basically. And that is important because of this thing that I installed called Serdai, which allows you to create serializable stuff. So I made some cheats. It's this cheat. Okay. So this is what we're going to be returning. Right? I'm going to first of all comment out this part of the return. But we'll go through this. So this means that it can be serializable, and it will be serializable by Serdai. And we're going to return a system. We're going to return the system info that has system on it, which has the name, which is usually, like, MacBook Pro. Blah, blah, blah. Kernel version. It has a OS version and it has a host name. Oh, no, that's the one that... We'll find out which one is what. We'll get there. Don't worry about it. Okay. Cool. So this is what we want to return. And how do you actually specify something that you want to return? So in this case, I'm returning a string, but I want to return a struct, which you can think of as an interface or a type. I don't actually still know the difference between an interface and a type, and I don't think anyone does. And I will die on this hill. So you just say, like, okay, I want to return a return system. No, no, no, no, no. What did I call it? I want to return system info. Okay, so and for that, we first need to get our system info, right? That would be important. So if I save now, I will get an immediate error that's like, girl, that's not a system info. And I'm like, you know what? It is not. But I'll make it one. Okay. So first thing I need to do is actually invoke sysinfo, which is the library that I'm using. And to do that, I say, okay, so let this equals system, which is already imported. So you can see it here. But if I remove it, this should import it automatically. So if I do system, yeah, that's the second one. There we go. That imported it. And you have a start all new all, one of the above new all. So you do this and then you do new all. And what does that do that instantiates the thing and goes gets goes gets English is not my main language. I'm trying to communicate here. Trust me, if you're not a native English speaker, this works. People feel really bad about making fun of your English. It works so well, too well. New one. That's great.

9. Retrieving and Displaying System Info in Rust

Short description:

Let's create a variable called system to get the system info. We can retrieve the host name, kernel version, OS version, and other details using the 'sys' object. Finally, we can return the system info and display it using the 'System Info' component.

Okay, we have that. Okay, so let's create a let's actually get the system info. Okay, so first of all, let's create a variable called system. Why does it let because constants are like actually aggressive constants, like constants have to be defined. If you create a constant, you have to define the type of the constant and it's a whole mess and we don't want to do that. So we're using let, so let system is gonna be something. It's gonna be a return system, which is the thing that we have here, which is gonna have all of this stuff. So let's do return system. And this is how you tell if this is gonna be an object, which is a struct of this type and return it. So now I can do control space. Option. It's option. Yeah, and I can tell all of the things that are in it. And this says it's an option string. So option string means there may be a string. There may be nothing. There will never be anything else. Trust me, Rust will yell at you if there's something else. Host name, and that is just, like, okay, sys dot host name. And that's about it. So that will return the host name. And we can do the same thing for all of them, kernel version, sys dot kernel version. Also, your computer is sys. Now you know. I didn't know. I found this out. Sys dot name. And what was the other one that I had? It was OS version, so sys dot OS version. Cool. So now we have this. So that doesn't actually return an error. And we can just return a system info now. So how do we do that? Okay. We say system info, and we return it with the system equal to the system. So it works the same way as JavaScript, in which you don't have, if the key and the value are the same, you don't have to, you just don't have to. You know what I mean. English. Okay. So now, instead of doing this, let me, json dot stringify info null 2, yes, there we go. So now we have the info of my computer. So we have a host name, which is, again, master MacBook Pro, I did not change the name of this computer, like an idiot, an OS version, I don't know what that means, and the kernel version of my MacBook. I have a MacBook, in case it hadn't been completely obvious by the fact that I've been sharing my screen for the last ten minutes. Okay. Cool. So we have this, and I made some, you know, fancy-ass components. So let's just use the component that I already made, which is called System Info, and then in here, pass the info.System. And yes, I'm doing this, and then I'm doing this, and then I'm saving, and then there's an error because this is not closed. There we go, and this is not imported. So let me import, SystemInfo, yeah, I know, I know, I'm sorry. Yeah, I know, I know, I'm sorry, I thought VS Code would import it by itself.

10. Retrieving Disk Information

Short description:

System Info and disks. I'm going to show you the beauty of Rust. If I get this.name, this will actually return something called an OSString, which I can turn into a STR, which is not a string, but it's a string slice. So to STR, and that will return me an option, which means there may not be a string, so I need to be aware that they may not exist. So I can't return this. And what I want to do is be like, okay, if this doesn't exist, just ignore it, just like burn my old app. So I need to unwrap it, and this still returns an STR, which then I need to be like, okay, that's cool. And I need to be as string. I think it's as string. It's not a string. It continues. It never ends. Oh, it's toString. I'm so sorry about that. How dare I? ToString, and now that's a string. And I think in my country that's beautiful. This is how we show love in my 50 seconds. Okay, cool. So now I just return the disks, right? That should be okay. I should... Yeah, no errors. Cool. And no errors shows up. So that's cool. So let me just do a little pre here. I have bad hearing. I have no idea what that was or if I was supposed to hear it. json.stringifyInfo.Disks.

System Info, and let me do the same thing for disks, so we don't have to do this in a beta again, because it's awkward. Someone's standing in here, it's very awkward. So yeah, there we go. So we have my computer info with all of that stuff, and the last thing that I want to do, the creme de la creme, that's all my French. That is not even French. That was English with a French accent. Show you my disks. I only have one disk, now what's in my disk. I don't know what the hell that was. So we have this in every computer, and that returns, okay, so that returns an array, right, and what is an array in Rust? It's a Vect. Vect. So let's say let's mute, and if you say mute, it means this thing's going to change. Please do not yell at me. This equals, okay, so Vect, like this. This is a macro, it's just a nicer way of writing Vect new. I don't know if you can see my hands. But yeah, so now let's do, let's go for each disk, so I'm going to say for disk in sys.disks, I want to do something, and what I want to do is say disks, disks.push. Yes, that is exactly what I want to do. And what do I want to push into it? I want to push a vect, a disk, so that's the type, and let's put this here, and I have all of this stuff, right? This makes sense. So I have some sheets for that, because you don't deserve to watch me write that. So that's pretty much all of it, except one, because I think this one is really funny. Okay, you guys, you're all going to love this. Okay, cool. So we need to get the name, right? And you would think that would just be like disk.name, but I'm going to show you the beauty of Rust. So if I get this.name, this will actually return something called an OSString, which I can turn into a STR, which is not a string, but it's a string slice. So to STR, and that will return me an option, which means there may not be a string, so I need to be aware that they may not exist. So I can't return this. And what I want to do is be like, okay, if this doesn't exist, just ignore it, just like burn my old app. So I need to unwrap it, and this still returns an STR, which then I need to be like, okay, that's cool. And I need to be as string. I think it's as string. It's not a string. It continues. It never ends. Oh, it's toString. I'm so sorry about that. How dare I? ToString, and now that's a string. And I think in my country that's beautiful. This is how we show love in my 50 seconds. Okay, cool. So now I just return the disks, right? That should be okay. I should... Yeah, no errors. Cool. And no errors shows up. So that's cool. So let me just do a little pre here. I have bad hearing. I have no idea what that was or if I was supposed to hear it. json.stringifyInfo.Disks.

11. Disk Cleaning and Info Retrieval

Short description:

Is everyone enjoying this? I hope so. Does anyone know what the first null does? We have two disks. MacBook by default has two disks. One of them isn't a real disk, just a partition. I had a function that cleans this. Let me show you. I.disks. Now I have info.disks. I have a disk with 59 gigabytes free. The crème de la crème, now I have a getInfo.

Is everyone enjoying this? I hope so. Null 2. Okay, cool. Does anyone know what the first null does? And we have two disks. And the reason for that, I'm going to show you my disk utility, is because MacBook by default has two disks. And one of them isn't a real disk. It's just a partition on your disk. And I don't know why, but Linux does the same thing, so I had a function that just cleans this. Because we deserve better.

Okay, so I'm going to say, setInfo equal to System. And that is I.system. Oop, no, not like that, boy. I.system. And then, I'm just going to say, like, disks equals, I think it's called clean disks. Yeah, that comes from utils. It basically just removes this trash. It's beautiful. I know. I write amazing, amazing functions. I.disks. And this should make the disks, you know, one disk. Oh, no, actually, it makes it no disks. That's also an op. Wait, wait, wait. Why? Wait, why was that async? There is not, it's a filter. Okay. I fixed that. So, that's good. That was dope.

Okay. So, I have info.disks and I have a couple, I have a little component that does the same thing. So, let me just say info.disks. I have zero seconds. .map, let's speed run this. Okay. D. Okay, there we go. No, no, no, no. I don't need that. I can't speed run it. I'm sorry. I failed you all. And then I need to do, okay, so this is the disk. Close it and I should have a disk in here. There we go. I have 59 gigabytes free. Wait, wait, wait. Thank you. Thank you. The crème de la crème now, I have a getInfo.

12. Creating a Button and SD Card Reader

Short description:

I'm going to make a button real fast. It says refresh. This is a very terrible SD card reader. I put this little bad boy in here and it works on my computer. It is from one of my retro handheld consoles. If you want to check out the code, it is on the QR code, because QR code's made a comeback, and it is on my GitHub. Please feel free to download it. The code looks better on it, I promise. Thank you and have a great day.

I'm going to make a button real fast. I'm going to speed run a button that onClick, that's not a click. Okay, onClick runs getInfo, right? So, what this means is that it will reload all the stuff and get me all the new stuff because and, oh, beautiful. Did I save? Yes, okay, cool. It says refresh. Okay, cool. You probably cannot see this, but this is a very terrible SD card reader because I lost the one that was good that I had. Why is it orange? I don't know. But it has an SD card in it, and an SD card is a removable device that if I, I mean, everyone knows what an SD card is. So, if I put this little bad boy in here and it works on my computer, apparently, okay, let's go. Do the thing. No? No? Yes. Okay. It is from one of my retro handheld consoles. Yeah, I have like five of them. We don't talk about it. I'm great with cash. But the thing is, it's not showing up in here. So if I refresh now, we have two disks, just to make sure that it works. And this one has a little icon on it. I tried to look out of like a, eject them and I don't know how. But that's about it, yeah. So with 0.0 seconds to go, I just want to say, if you want to check out the code, it is on the QR code, because QR code's made a comeback, and it is on my GitHub. Please feel free to download it. The code looks better on it, I promise. And yeah, thank you and have a great day.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Vue.js London Live 2021Vue.js London Live 2021
8 min
Utilising Rust from Vue with WebAssembly
Rust is a new language for writing high-performance code, that can be compiled to WebAssembly, and run within the browser. In this talk you will be taken through how you can integrate Rust, within a Vue application, in a way that's painless and easy. With examples on how to interact with Rust from JavaScript, and some of the gotchas to be aware of.
JSNation 2022JSNation 2022
22 min
Makepad - Leveraging Rust + Wasm + WebGL to Build Amazing Cross-platform Applications
In this talk I will show Makepad, a new UI stack that uses Rust, Wasm, and WebGL. Unlike other UI stacks, which use a hybrid approach, all rendering in Makepad takes place on the GPU. This allows for highly polished and visually impressive applications that have not been possible on the web so far. Because Makepad uses Rust, applications run both natively and on the Web via wasm. Makepad applications can be very small, on the order of just a few hundred kilobytes for wasm, to a few megabytes with native. Our goal is to develop Makepad into the UI stack of choice for lightweight and performant cross-platform applications. We intend to ship with our own design application and IDE.
Node Congress 2022Node Congress 2022
8 min
High Performance Node.js Powered by Rust and WebAssembly
In the post Moore’s Law era, due to limitations of the hardware, we need to squeeze more performance from the existing hardware. That means that the native code provides the best performance. However, the prevalence of native code on the server-side presents challenges to application safety and manageability. The rise and advent of Rust and WebAssembly offers new ways for developers to write high performance yet safe Node.js applications.
In this talk, I will cover the basics of Rust and WebAssembly, as well showcase how to go about their integration with Node.js. You will learn how and when to design a hybrid web application. How can you code the high performance functions in Rust in a Web Assembly virtual machine and finally how to tie everything together in a Node.js JavaScript application.
Node Congress 2023Node Congress 2023
22 min
Type-safe bindings for Node.js with Rust and WebAssembly
This talk will teach you how to write performance-critical Node.js modules without the burden of distributing platform-dependent artifacts and using the C/C++ toolchain. You will discover how to smoothly integrate Rust code into your Node.js + TypeScript application using WebAssembly. You will also learn how to avoid the typical WebAssembly serialization issues, and understand when other alternatives like Neon or Napi.rs are preferable. Together, we will cross the language bridge between Rust and Node.js while preserving the familiar DX you're used to.