In this episode of React Native Radio, Robin and Mazen are joined by Marc Rousavy to break down transforming packages to Nitro and why it’s a big deal for high-performance native modules. They dig into Nitro’s origins, how it stacks up against TurboModules and Expo, and what’s coming next for VisionCamera.
Show Notes
Connect With Us!
This episode is brought to you by Infinite Red!
Infinite Red is an expert React Native consultancy located in the USA. With over a decade of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter, core React Native contributors, creators of Ignite and Reactotron, and much, much more), Infinite Red is the best choice for helping you build and deploy your next React Native app.
Jed Bartausky:
Welcome back to another episode of the React Native Radio Podcast, episode 351: Transforming Packages to Nitro with Marc Rousavy.
Mazen Chami:
Welcome to 2026, React Native Radio fans. Do we have another good episode for you today? I’m Mazen, she’s Robin, and we’re React Native Radio. We are joined by the infamous Marc Rousavy. Marc, welcome to the show.
Marc Rousavy:
Hey you guys, thank you so much for having me. I’m super excited.
Robin Heinze:
Better to be famous or infamous?
Marc Rousavy:
I don’t know. Probably infamous. I don’t know.
Robin Heinze:
I was like, I don’t know if “infamous” is a good thing.
Mazen Chami:
Is it not?
Robin Heinze:
I don’t know.
Mazen Chami:
Alright. The editors will just get rid of the—
Robin Heinze:
No, they won’t.
Mazen Chami:
Anyways, it’s always good to see you. Welcome back to the show. Last time we had you was RNR 310. We were talking about Nitro right before it came out. And this is a great segue because we’re going to continue building on Nitro now. It’s been out for a while.
Robin Heinze:
It’s been out for over a year and a half. How old is it? It’s not baby Nitro anymore.
Marc Rousavy:
Yeah, it’s like—wait, when was the episode? I think a year and a half maybe. I don’t think it’s two years. I think it’s like October ’24, I believe.
Robin Heinze:
Oh yeah, over a year ago.
Marc Rousavy:
Yeah, definitely over a year ago.
Robin Heinze:
Side note, Mazen—why does it say 2024 in the episode title? In the show notes, we have notes that we’re looking at and it literally says 2024.
Mazen Chami:
What? I think I copied that template. Oh, that’s probably what happened. Yeah, I forgot—change the year.
Robin Heinze:
From the last time you were here in 2024.
Mazen Chami:
Yeah. Anyways. Okay, Marc, for our listeners that don’t know you or that do know you, please go ahead and introduce yourself.
Marc Rousavy:
Yeah, so I’m the infamous, apparently, Marc. I go by the handle mrousavy online, and I do a lot of open source. I build a few apps. I run an app development consultancy here in Europe, in Vienna, and we’re—yeah, I think we’re probably most known for our open source stuff. So that’s React Native VisionCamera, React Native MMKV, and now also Nitro and everything associated with it. So we built a few Nitro modules like React Native Quick Crypto or React Native MMKV now as well, React Native Nitro Image. And there’s a ton of community modules. Yeah.
Mazen Chami:
Is VisionCamera on Nitro yet?
Marc Rousavy:
Yeah, that’s the exciting thing. Back one and a half years ago when I was on the podcast, I teased everyone about Nitro and the behind-the-scenes and the insights, and all of your listeners got some early information before it was public. And now I think this episode is going to be the same because VisionCamera is being rewritten to Nitro and it’s a private repository. I’m not doing it open source—well, it’s going to be open source, but it’s not right now. And I have a lot of learned lessons and a lot of cool new interesting facts about it and it’s going to be a huge release.
Mazen Chami:
Well, I guess we need to have you back on the podcast for just that. Okay. I think I’m getting ahead of myself here. Before we get into our topic, let’s hear from our sponsor. Infinite Red is a premier React Native consultancy located fully remote in the US. We’re a team of 30 senior-plus-level React Native developers and support staff and have been doing this for nearly a decade—well, more than a decade.
Robin Heinze:
More than a decade. We need to update our sponsor read.
Mazen Chami:
Yeah. If you’re looking for React Native expertise for your next project, hit us up at Infinite Red slash radio. Don’t forget to mention that you heard about us through the React Native Radio podcast. Alright, now let’s get into our topic: Transforming Packages to Nitro. Spoiler: in getting ready for this episode, Robin and I watched the “How to Build a Nitro Module” YouTube video and it was—
Robin Heinze:
Great. It was a very good video.
Mazen Chami:
It was very good. Thank you. We learned three things. You had a very tasty burger.
Robin Heinze:
Oh yeah, we got to ask how the burger was. You said you—
Marc Rousavy:
You guys have to come to Vienna. I got to show you the burger place—it’s amazing. I mean, I don’t know how it tastes for Americans, but for European standards it’s the best burger here.
Mazen Chami:
Good.
Robin Heinze:
Good. Okay. I’ll book a trip.
Mazen Chami:
Yes.
Robin Heinze:
Yep. It’s on my list.
Mazen Chami:
We’ll be right there. Yeah. And then should we, before we start this episode, take a coffee—what did you call it? A coffee boost?
Marc Rousavy:
A productivity coffee boost, tactical coffee, something like this. I dunno. Tactical coffee.
Mazen Chami:
Yeah, you need tactical coffee. Definitely need a tactical coffee. And I do. Every time the background elevator music came on—
Robin Heinze:
Oh yeah, when you were doing the build. That was a really good test. That was funny.
Marc Rousavy:
Thank you. Thank you. Yeah, I also learned two things when doing the video. I learned, first of all, you can’t one-shot a tutorial, and second of all that video editing is much, much, much harder than it looks. Like, when you consume the video, for a 30-minute video, I probably took a full day just for cutting it and uploading it.
Robin Heinze:
You just have to look at Jamon’s YouTube channel to figure out that he figured out how much time anything takes. That’s why there’s only five videos up there. Very good ones. But he is like, “Yeah, it took my whole day.”
Marc Rousavy:
Yeah, I can imagine. Yeah.
Robin Heinze:
Awesome. So let’s give our audience a bit of a background in Nitro. First, just set the stage. If you walk through the docs, you kind of get the story of using Nitro: you create a Nitro module, it has a Nitro JSON file, which defines everything—what everything’s going to be called. You write some spec files in TypeScript, then you run Nitrogen, which is your codegen library. That’s right. Amazing name, by the way. I think we must’ve asked you this last time, but did Nitrogen come first and then Nitro from that? Or did you just have a eureka moment? You’re like, “Nitro gen… oh my God.”
Marc Rousavy:
Yeah, it was exactly like that. So it was Nitro first because it’s car terminology, same as TurboModules. So it got inspired by the name Turbo, which is “boost your engine,” and Nitro is the same thing. And when I wanted to build the codegen, I was like, “How do I call it? Nitro codegen?” And then Nitrogen. One thing actually changed since the last time we recorded, because I now have the “nitrogen” name on npm. Back then I had “nitro-nitrogen,” and now it’s “nitrogen.”
Robin Heinze:
Oh, amazing. Did you have to get someone to give that up? How did that work?
Marc Rousavy:
Yeah, so it was some guy from Microsoft, I think. He was working at Microsoft or has been working for Microsoft, I dunno. And I emailed him a couple of times actually and didn’t receive a response. Maybe it just went into spam or something. And after talking to Tommy—who from Microsoft who’s working on React Native Windows—great guy. Met him in, I think it was Poland last year. And he told me to reach out again, maybe elevate somehow because he has some connections there. And then I just tried to ask again. I sent another email and this time he replied and he was like, “Oh yeah, sure, I can give up the name.” I was like, “Oh damn, that was easy.” So great guy. It’s amazing.
Robin Heinze:
I’m surprised he didn’t make you pay a bunch. Hold it for ransom.
Marc Rousavy:
Yeah, yeah. I don’t know how much I would’ve paid for the name, to be honest. I mean, after all, it’s open source, right? But yeah, that was really nice.
Robin Heinze:
But it’s really cool. It’s really cool that it’s actually called Nitrogen. That’s amazing. But anyway—so you run Nitrogen and it generates a lot of the native specs and a bunch of stuff for you. And then you add your actual implementation to go along with the spec. And you do have to register the hybrid objects that you create in your Nitro JSON—that’s what that’s for. But basically this is a framework for making native modules and makes it really super easy and fast.
Marc Rousavy:
Right. Yeah.
Robin Heinze:
Is that kind of the gist?
Marc Rousavy:
Yeah, that’s the whole idea. We can get into some more details about which objects have to be hooked up and what actually is the difference between this and Turbo or Expo and when to choose what later on.
Robin Heinze:
Yeah, that’s definitely the direction I’m going. But I guess to start with—why did you create Nitro and Nitro modules? What was the problem that you were fixing?
Marc Rousavy:
So we built a 3D rendering library, which just used Filament as its rendering engine. And we wanted to expose that to React Native. And back when we worked on that, I think it was 2022 or 2023, we had to write all of the JSI bindings ourselves. And in Filament you have a ton of different objects. You have your scene, you have your camera, you have your light or multiple lights, you have your objects, you have your models, you have your textures—all different objects, right? Each of those have state, which is native C++ state. It’s like a Filament value, a Filament state, a Filament object, whatever. And so we wrote all those bindings using raw JSI APIs.
For example, a coordinate XYZ was just three JSI values holding a double. And it became super complex at some point because then everything was a JSI HostObject. We had this hybrid approach where sometimes we used some JSI macros—like C++ macros like VisionCamera did back in the day—to define a JSI host function to just remove some of the boilerplate, and still the boilerplate was a lot. It was so much JSI work and only so little Filament work that we had to do.
So we figured out, okay, we need to build some kind of abstraction on top of JSI so we can get to actually building the stuff that we want to build, instead of just writing JSI stuff all the time. We got rid of all of the C++ macros and built an abstraction called “hybrid object” instead, where you can use C++ templates to register your functions.
So let’s say it’s a hybrid object representing a model. It has its native state in C++, and then you can register a method or a getter or whatever using the C++ templates that we wrote. For example, a move function which just takes three parameters and doesn’t return anything. You just pass this to a C++ template and the template knows which arguments are being used. C++ templates are like generics in other languages. If you only know TypeScript, then you don’t know about that stuff. But for all of the people who are actual programmers, it’s generics and then templates and stuff like that can infer types and do different stuff on type metadata.
And the templates knew, okay, this is a method. We know the method name, we can register it using JSI—register, set property, whatever. And then to unwrap the three parameters, we know the type of the parameters, which is double three times. So now we use the C++ template for doubles and it’s recursively resolving each type using our templates that we defined back then.
And so this system was super cool because it was also super flexible and you could define any arbitrary type using the JSI converter template. And so essentially every type could be convertible from JSI to a C++ value. And back then we had some optimizations around caching, around throwing errors, and making sure it’s safe and it’s not doing any unsafe unwraps and stuff like that.
And since then it evolved a lot and we gave it the name Nitro and extracted it into a separate package because I had all of those pain points before in VisionCamera and in MMKV, and it’s the same story all over in those packages.
And so I extracted it with the long-term goal of rewriting everything in Nitro because what I was doing is essentially the same as in Nitro, but with less safety, sometimes less performance. You can write the JSI module with raw C++ JSI values and still be slower than Nitro because of all of the optimizations. You can use JSI wrong—you can use a HostObject instead of native state. You can not cache property names. You can do unsafe unwraps of types. We’ve seen this in the recent Rust Cloudflare thingy where you just unsafely unwrap something, everything crashes. So you need to be safer on those things.
Yeah, so it’s just this one system, this one toolbox that I figured there’s no runtime cost to it. It’s the opposite—it’s faster. And the long-term goal was to rewrite all of my libraries in Nitro and also obviously help the community build better modules so everyone can use Nitro themselves and build modules themselves.
Robin Heinze:
So it sounds like it was a little bit twofold. It was avoiding all the boilerplate you were having to deal with JSI, but also adding a level of protection—both type safety, but also performance—saving yourself from yourself basically.
Marc Rousavy:
Exactly. Yeah.
Robin Heinze:
Well, the more boilerplate you’re writing, the more chances you have to screw something up.
Marc Rousavy:
Super error-prone.
Mazen Chami:
Yeah.
Robin Heinze:
Yeah.
Mazen Chami:
So I assume then the reason why Nitro was born—like you said, boilerplate and safety—why not just go with Codegen? It’s already built in, it’s performant enough, or even just an Expo module too?
Marc Rousavy:
Right. So Expo modules doesn’t support C++ as a target. So that’s out immediately for the stuff that we’re doing. Like MMKV, for example—it’s a C++ module. VisionCamera frame processors are all C++.
Robin Heinze:
Just to pause on that for a second—those are written in C++ and probably have to be written in C++ because… is it performance? Is it capabilities of C++ that you can’t get from other things, or…?
Marc Rousavy:
So it’s a mix of everything. MMKV is in C++ because it’s the lowest-level abstraction you can choose for the MMKV library because MMKV is just built in C++—the core library. And they build front ends for Objective-C, for Java, but those essentially just wrap C++. So there’s no sense of me using those because it’s just an unnecessary wrapper. So instead I just use C++ directly and there’s no layer in between.
For Filament, it’s the same. Everything is written in C++ and they don’t even have Java or Objective-C bindings, so you just have to use it from C++, which is pretty obvious since it’s a high-performance rendering engine.
And in VisionCamera, we wrote most of the parts in C++ because it’s cross-platform and I don’t want to rewrite the same code twice. And it’s also one abstraction less for frame processors because it’s just something that runs on a separate runtime, which is also just JSI APIs under the hood. So yeah, most of that part is in C++—the actual camera stuff is not in C++.
Which brings me to another point—mixing languages. So in Nitro you can actually mix the platform language and C++ (or any other language that Nitro supports). So in a sense, you can write one part of your library in C++ and the other part in Swift or in Kotlin—maybe in the future also in Rust or any other language—and mix and match those objects together.
And this is actually how MMKV works. Everything is in C++, but there’s one single hybrid object—or essentially one single function—in a platform language. So that’s Swift and Kotlin. We actually call that one function directly from C++ and it’s implemented in Swift or Kotlin. But the C++ code base—the cross-platform C++ code base—doesn’t even need to know about this because it’s just generated by Nitro and it looks like any C++ API. The actual implementation is in a platform language.
But Nitro allows you to mix and match those languages seamlessly without having to worry about the platform interop at all, or without having to do an “if Apple / if Android” check or whatever. It’s just one call. And that’s super, super common in our libraries.
Filament has the same, right? Everything is in C++. And then there’s some small specifics in platform languages like the actual view, for example, and the asset loading, which uses the Android asset catalog on Android and the iOS bundle on iOS. And in C++ in our implementation, we just call load and give it a string and that’s it. And we don’t care how it’s being loaded. So that’s super, super flexible.
Robin Heinze:
It seems like using Swift or Kotlin—the individual platform implementations—is mostly a developer convenience. Is there any reason that you would choose to do the multi-platform versus doing just the single implementation in C++?
Marc Rousavy:
Well, you have to use platform languages if you want to use platform APIs. So that’s loading from the asset catalog or from the bundle—that’s a Java or Kotlin API or Swift API, which you cannot call from C++ directly.
You will be able to call it using Nitro if you implement it in Swift. And then the stuff that Nitro generates is a C++ class and you can call that from C++ (or essentially also JavaScript, obviously). So with Nitro you can make it cross-platform, but by default, Android doesn’t care about JavaScript or iOS—they just have their own APIs and you can call them.
There are some APIs that are callable from C++, like on iOS, for example, you have the threading APIs or dispatch queue, which are essentially just C APIs. But for that, you would still have to do a conditional import—like if Apple then import dispatch queue—and then you can call dispatch queue. And on Android you do the stuff differently—you import Android whatever. So yeah, we want to obviously eliminate that stuff and just use the native way of doing things, expose it to JavaScript, which as an intermediate step also builds a C++ wrapper around it, which is the stuff you can call in Nitro.
So yeah, that’s this load-asset thingy that I mentioned before, and it’s super convenient for our libraries.
Mazen Chami:
So in theory for my package, I could have a hybrid object that is written in Swift and Kotlin while having a hybrid view—or vice versa—that is written in C++ for both platforms and still accomplish the same goal, right?
Marc Rousavy:
Yes. The only thing I need to correct, Mazen, is you cannot build a hybrid view in C++. So hybrid views have to be platform languages because they’re platform APIs, right? Android Views is a Kotlin/Java API. There’s no C++ way for that. But yeah, if it’s a platform view or if it’s just a view component, then you can pass C++ stuff to it.
In theory—I’m saying in theory—because we currently only have one-way bindings because we’ve never had the need to call a C++ function directly from Swift and Kotlin—only the other way around because of the platform interop—but it wouldn’t be too tricky to add interop for that, and it’s actually on the roadmap as well for Nitro.
Mazen Chami:
Nice. Nice. So with that being said, how do you see Nitro being used? Nitro modules being used differently by app developers versus a library maintainer?
Marc Rousavy:
So essentially Nitro is a toolkit for library developers. And as an app developer, you just consume the npm package. So you just have the runtime of Nitro modules. You try to keep it always up to date because it’s backwards compatible, not forwards compatible.
So if you build a module—a Nitro module—on a newer Nitro version than the runtime version you have, it might not be compatible. So you always have to make sure your Nitro runtime version is up to date.
And that’s the only thing the app developers should worry about—just updating their Nitro modules version, making sure they are on a modern toolchain because parts of it require a few modern—lemme do that part again—because Nitro requires a few things that are only released in recent Xcode updates or NDK updates.
So you need to use Xcode 16.4, I think, is the minimum version. And on the NDK, I think you have to use 27 or something. But it’s fairly common requirements. I mean, Xcode—we are already one major version ahead of that. But yeah, just be aware of those.
Robin Heinze:
I’m pretty sure our audience is probably mostly app developers versus library authors, and I know a lot of them use Expo and so they may pull up Nitro thinking it’s really cool and then realize you can’t really use it. If your app is on Expo, is there a solution for that in the future or is this kind of just going to be one way or the other?
Marc Rousavy:
No, you can use Nitro on Expo. There’s no limitation around that. You can mix and match. So we use—a couple of our clients actually have Expo apps and we build Nitro modules for them.
Robin Heinze:
Do you just have to build a config plugin? How does prebuild work with the sort of the setup that Nitro requires?
Marc Rousavy:
You don’t have to build a config plugin unless you’re changing something. A config plugin is only for the iOS or Android project, I think.
So you can use a Nitro library—or a library built with Nitro—in the same way that you can use any other native module. You cannot use it in Expo Go, obviously, because it’s native code. But in an Expo prebuild or EAS-built app, you can just use any Nitro module.
You just have to install React Native Nitro Modules as the base runtime, which is a super small library. But then yeah, you can just use it without any config plugin, without nothing. So nothing changes for Expo developers.
Mazen Chami:
Same installation process. So running Nitrogen will still tie into Expo and all that kind of stuff.
Marc Rousavy:
I think that might be a common misconception. Nitrogen is not being executed by the app developer. So the idea is that the library developer runs Nitrogen and then ships the generated artifacts to npm as well—in the same way that they run TypeScript build or their whatever. Nitrogen also has generated artifacts. It’s mostly just C++ files, and those are shipped to npm. And yeah, the idea is that you have a ready-to-use package.
I don’t like the idea of— I mean, it has its ups and downs—like React Native’s Codegen runs on app build, which as long as everything works is pretty cool because then the npm package gets smaller and also you can update your TurboModules code generator version. Maybe there’s some performance improvements in the future, and the library developer doesn’t have to do that manually because at the end of the day, the consumer generates specs.
But for Nitrogen, I chose to do it differently because I just wanted it to be a ready-to-use artifact. I want the library developer to have less pain dealing with Codegen failures. We’ve seen a couple of times when the app just doesn’t build because of Codegen or empty header files or whatever. I think they fixed all of that now, but still, I like the idea of just having everything ready and also decreases build times for the user because it doesn’t need to generate anything.
Mazen Chami:
Fair enough. I mean, I can also speak to what I was doing this morning as an app developer. I was working on updating our client’s packages to latest, and one package that I’ve been using heavily and really enjoy using is UniStyles. And UniStyles is a JSI library—UniStyles is leveraging Nitro underneath the hood. So I did go ahead and update Nitro to the latest version, created my build, it crashed. I realized I didn’t upgrade Nitro, so I had to come back and update Nitro to the latest version and then it kind of worked. So that’s pretty cool that you kind of have the collaboration of all that with Yassine at UniStyles, but then also there’s so many other packages out there.
I know on the Nitro website you have what you call “Awesome Nitro Modules” showing off all the modules. And I know Frank Calise here at Infinite Red—so on his GitHub, frankcalise/awesome-nitro-modules—there’s also a GitHub repo that he’s keeping up to date with all the Nitro modules out there. I think he has a couple PRs open to merge in some stuff, but it’s great to see all these different libraries making the switch over to Nitro and kind of leveraging this cool feature that you’ve built.
Marc Rousavy:
Yeah, yeah. UniStyles is a great library. And I get the pain that you have to think about Nitro—about upgrading Nitro—and if you forget about upgrading Nitro, your app might not build if one of your libraries uses a newer version or was generated on a newer version of Nitro.
Yeah, I guess that’s a bit unavoidable. It will obviously change in the future. The more stable Nitro gets—or the less changes Nitro has—the more stable it gets. I think right now it’s been a while since we had a breaking change. I do think that the last release had one change which requires you to be on the latest release.
But still—I mean, it’s super easy to update Nitro, right? You don’t have to do any file changes or whatever. You just bump the version on npm and that’s it.
Robin Heinze:
Which is way easier than all the other things we have to upgrade. It was very— all the X dependencies—everything… we’re used to painful upgrades. And that sounds pretty painless.
Mazen Chami:
Yeah, no—in my example, I just bumped it up to I believe 0.33.0 (or whatever that latest is), ran prebuild, ran my apps and they both worked, so—
Marc Rousavy:
Awesome.
Mazen Chami:
And we’re great. Now I’m just battling the CI. I don’t know what’s going on over there.
Marc Rousavy:
I think actually I can help you debug that. I think it’s Xcode version because maybe you’re running on a macOS-latest runner, which is not using Xcode 16 yet. And so I added a new feature in Nitro, which is new recycling, and it generated some code that works fine on Xcode 16, but might not build on Xcode 15. So we’re looking into that right now to fix it. So maybe you just have to upgrade to 0.33.2 when it releases soon to get that fixed.
But yeah, the Swift compiler is a bit annoying sometimes. And old versions of the Swift compiler generate way different code than newer versions.
Yeah, but I’ve seen that build failure. You can also just upgrade your CI to Xcode 16.
Mazen Chami:
Yeah. Yeah. Thanks for that tip. I’ll take a look at that.
Well, awesome. I think we’re kind of wrapping up here. Marc, I really appreciate you. Thank you for coming onto the show. It’s been nice chatting and learning what’s happening with Nitro. What’s in the future for Nitro—what’s next?
Marc Rousavy:
So obviously VisionCamera. VisionCamera is going to be the big most-anticipated Nitro release. I think I can tease a few features that haven’t been possible before that will be possible now.
So one of the most anticipated features is using native Worklets instead of React Native Worklets Core. So if you remember back in the day, we built—Mazen and Marlow built—React Native Worklets Core, a worklet runner that is actually flexible for workloads outside of just Reanimated. So not just UI updates, but also VisionCamera frame processors or any background threads or whatever.
And back then the Reanimated team wasn’t super cooperative about getting their worklets or their Reanimated runtime into VisionCamera. So I had to do a lot of stuff myself. But all of that changed. Now the Reanimated team—they have some new people on there. For example, Thomas, super cool guy—he’s been helping me a lot on getting React Native Worklets ready. A lot of help from them.
Yeah, so we’re going to deprecate React Native Worklets Core soon. And since the Reanimated team built React Native Worklets as a standalone library, we’re going to just agree on that standard. And so that’s going to be the standard for VisionCamera.
And that’s also much, much simpler now with Nitro, because back in VisionCamera v2 till v4, I wrote a lot of JSI code myself—a lot of that C++ boilerplate. And with Nitro, all of that is completely gone.
I have one C++ hybrid object which is responsible for creating the async queue, which is a type by the native Worklets team. So I just create the async queue, pass it back over Nitro, and it’s a custom type in Nitro, so it’s still type safe even though it’s an external type which is not using Nitro.
So the async queue is something the Reanimated team defined as a JSI HostObject. And even though it’s not using Nitro, you can still use it in Nitro as a value type.
So I’m creating that in VisionCamera, and the rest is all just JS code and it’s super, super straightforward. So there should be way less errors now, no more build errors and stuff like that. So stability is a huge, huge thing and I think it’s going to be great.
Another thing is the in-memory image type. So that’s one thing that has been bugging me since day one of VisionCamera. When you capture a photo, VisionCamera actually writes that photo to a temporary file and then gives you the path as a string. And then to display it again immediately—like for example on Snapchat—you take a photo and you want to display it, you render an Image component, which you give it the path to the file, which then loads the image from the file again.
So it’s like writing to file just to read it immediately again, which is super unnecessary.
So in VisionCamera v5, I can now use the image type which I’ve built—React Native Nitro Image. Maybe you’ve heard of it. So VisionCamera just returns the image type from React Native Nitro Image—again, an external type. So it’s just imported in VisionCamera and I can use it in VisionCamera.
And so you don’t have to write any file—you can just display it immediately in memory. So faster photo capture, essentially less file I/O, less potential room for error—like if there’s no storage left or whatever.
It’s super obvious to a native developer that this is how it should work, but for React Native it’s been different since a long time. I think Expo also has a similar concept, but in VisionCamera it’s fully type safe. Everything is handled over Nitro.
So that’s the cool part. And the image component also has a lot of helper functions like saving to file, rotating, cropping, scaling, whatever—and even manipulating pixels.
And then all of the in-memory types that VisionCamera returns are much safer now as well. No more crashes around there because I’ve written them in C++ with the boilerplate before and it’s super, super hard to bridge them to native code. And it’s also going to be faster because Nitro is faster than the code I wrote before.
And when I talked about—in-memory types, just to elaborate a little bit more—it’s the Frame from frame processors is going to have a lot more features, a lot more methods, a lot more properties. The image returned by capture function is going to be better. The movie video file by movie capture is going to be better. Snapshot is going to have more functionality.
And then one other cool thing is that with this hybrid object approach in Nitro, everything is—you have your instance-based API where there’s a base type and you can implement that in a subtype.
So for example, in VisionCamera, you can add any output to the camera. It’s just a hybrid object called CameraOutput. And so photo capture is a PhotoOutput which extends CameraOutput. A video output is VideoOutput which extends CameraOutput. So all of those outputs extend CameraOutput, which allows you to implement your own output and make it much more flexible and add whatever output you want to the camera.
So because we’ve had this before—we built the Visco app, the photo capture app—and they wanted to have HDR capture, which was a lot of monkey patching in VisionCamera.
And with VisionCamera v5, you can now just define your custom HDR pipeline with your own proprietary processing software or whatever, and add it as a camera output to the camera. And there’s no patching required, and you can maintain the output yourself—just conform to the protocol. That’s it.
So super, super flexible now, which means that VisionCamera is going to have more outputs. One of those outputs is going to be a depth output. So you can actually stream depth data in real time. Your phone has a LiDAR sensor or Face ID sensor, whatever, and you can actually stream that in real time using VisionCamera v5.
Mazen Chami:
That’s awesome. Yeah, that’s a lot of cool stuff coming down the pipeline. And it sounds like you’re giving back to so many other packages that you should create your own stack—like the Marc Stack—everything lives under that. Yeah, Nitro is really turning into an ecosystem, I guess.
Marc Rousavy:
Exactly. Yeah.
Mazen Chami:
And my last question here—which I’m not going to ask for a specific reason—you’ll see why—but what’s one idea you’d love an audience member to tackle with Nitro Modules? But I’m not going to ask you that question because real soon I’m going to have you on React Native Live and we will build a Nitro package on there. So save that idea for that package so that we can build it together.
Robin Heinze:
Have we told the listeners yet what React Native Live is?
Mazen Chami:
Well, so the listeners know of React Native Mornings at this point. React Native Live is basically our rebrand for 2026 and kind of moving forward for React Native Mornings.
So moving forward, React Native Live will have its own YouTube link, website, and all that cool branding that comes with it.
Robin Heinze:
It’s a whole relaunch. It’s very exciting.
Mazen Chami:
It’s a whole relaunch of it. We still have the six episodes that we recorded prior still on our YouTube channel. But moving forward for 2026, we’re going under the name React Native Live.
First guest is Yassine. By the time this comes out, Yassine will have gone over UniStyles and UniWind together. And then right after this episode comes out, probably Marc will be on to talk about Nitro together on the Live.
And there’s a lot of cool guests slated to come on there too, but you don’t want to miss the infamous Marc Rousavy.
Well again, Marc, I really appreciate you coming on. Before we sign off, where can our listeners reach out to you if they have any questions?
Marc Rousavy:
Yeah, you can reach out to me over GitHub issues if you have any issue using Nitro. We do have a community Discord as well, which I’m going to shamelessly market here. So it’s linked on either marlow.com/discord or on our open source repos in the READMEs.
And I believe some of you guys are on the Discord as well. It’s a great place to just chat about the libraries, about React Native in general. Yeah.
Robin Heinze:
Not just Nitro—all the other Marlow libraries like VisionCamera, Filament, MMKV, etc.
Mazen Chami:
Right. And also, I’ll add it to the show notes so our listeners can come check. We’ll add your YouTube video, the docs, a bunch of links in the show notes. So make sure to check those out this time.
Marc Rousavy:
And I think lastly on Twitter as well—or on X.
Robin Heinze:
Still Twitter.
Marc Rousavy:
Twitter. Yeah.
Robin Heinze:
I enjoy so much that—what, two years later? More than that—I still call it Twitter. I still type twitter.com in my browser. It’s still Twitter.
Marc Rousavy:
Even though x.com is way faster to type, it’s—
Robin Heinze:
No, it’s Twitter. Be Twitter.
Mazen Chami:
Well, awesome. That’s it for our episode. And I guess just kick off 2026 on the right foot. Robin, do you have a mom joke for us?
Robin Heinze:
I have one from Gant, so you know it’s good. I just got fired from the keyboard factory. I didn’t put in enough shifts.
Marc Rousavy:
That one’s terrible. I love it.
Robin Heinze:
I know it’s good because it’s terrible. There you go.
Mazen Chami:
Alright everyone, thank you all and see you all next time.
Marc Rousavy:
Thanks so much for having me. Thanks.
Jed Bartausky:
As always, thanks to our editor, Todd Werth, our assistant editors, Jed Bartausky and Tyler Williams, our marketing and episode release coordinator, Justin Huskey, and our guest coordinator, Mazen Chami. Our producers and hosts are Jamon Holmgren, Robin Heinze, and Mazen Chami. Thanks to our sponsor, Infinite Red. Check us out at infinite.red/radio. A special thanks to all of you listening today. Make sure to subscribe to React Native Radio on all the major podcasting platforms.




There’s no perfect time to get started. Whether you have a formal proposal or a few napkin sketches, we’re always happy to chat about your project at any stage of the process.
Schedule a call