Beyond React Native: How Valdi Redefines Cross-Platform Development


i spent last weekend trying to build a simple habit tracker. nothing fancy. just a few screens, some buttons, a list. i wanted it on my phone and my partner's android. figured i'd knock it out in a day.
four hours in, i was screaming at expo. my "native" app felt like a webpage wearing a fake mustache. the animation jank was giving me a headache. and don't get me started on the bundle size. i tweeted something angry about cross-platform frameworks and went to bed.
monday morning, my coworker slack'd me a link. "snapchat open-sourced their framework." i rolled my eyes. another react native clone. but i clicked anyway.
you've probably done this. i know i have.
I used to think native performance meant writing swift and kotlin separately. that's what apple and google want you to believe. their docs practically whisper it.
but valdi doesn't play that game. it takes your typescript and compiles it straight to native views. no webview. no javascript bridge. no awkward translation layer that makes your ui feel like it's running through molasses.
here's what i mean. i copy-pasted their timer example into vs code. wrote a class component that looked oddly familiar but wrong. no jsx return statement. just a render function that... returns void? i stared at it for ten minutes.
the first time i tried to run it, the cli threw an error about missing cmake. annoying. i'd have to install native build tools. but then it worked. and the app on my phone? it scrolled like butter. actual, real butter. not that margarine react native sells you.
look, here's what i wish i'd known: it's not react. it looks like react because they borrowed the component mental model. but under the hood it's a c++ layout engine talking directly to uikit and android's view system. your typescript gets compiled ahead-of-time. the hermes runtime is only there for business logic, not ui.
my coworker tried to animate a list item. used a spring animation from their docs. it ran on the main thread automatically. no worklet nonsense. no "use native driver" flags. just worked.
the problem isn't what you think. it's not another framework to learn. it's that you've been lied to about what "cross-platform" has to mean.
Most tutorials tell you to just use react native and call it a day. they've been saying it for years. facebook's ecosystem is huge. the community is massive. why fight it?
but valdi's team at snap spent eight years fighting it. quietly. while we were all wrestling with reanimated and flipper, they were building this thing for their own app. snapchat. the app with half a billion users who send disappearing photos of their foreheads.
i found that detail buried in a hacker news comment. eight years. they didn't open source it until now because it was just... their code. internal tooling doesn't need fancy docs. it just needs to work for the people who built it.
the first time i tried to understand their state management, i got lost. they use class components. actual classes with generics. timer component extends statefulcomponent<timerprops, timerstate>. it felt like stepping into a time machine.
but then i saw why. it's not for elegant abstractions. it's for performance. the framework needs to know exactly when to update which part of the view tree. classes give it that control. functional components with hooks would hide too much.
and the code generation? they auto-generate kotlin and swift bindings from your typescript interfaces. i changed one interface, and the android build folder showed a new .kt file. spooky.
here's a question people always ask: "is this ready for production?" well, snapchat's been using it for their main features. so yes. but also no. the docs admit it's beta. the tooling needs "battle testing." translation: we wrote this for ourselves and we're still figuring out how to explain it.
What actually happens when you save a file is wild. i'm used to metro bundler taking its sweet time. hot reload in react native feels like sending a postcard and waiting for a reply.
valdi? near-instant. i changed a label text, hit save, and the phone updated before i could look up. my coworker thought i was faking it. we recorded it in slow motion just to prove it wasn't a trick.
the mechanism is different. they're not shipping javascript over the wire. they're recompiling just the changed component and pushing a tiny binary diff. it's more like flutter's hot reload than react native's. but without the weird "widget" vocabulary.
i spent an hour trying to break it. added a thousand list items. scrolled like a maniac. the viewport-aware rendering meant only visible cells existed. my phone stayed cool. my battery didn't drop 20% in five minutes.
but then i tried to add a third-party library. any library. npm install some charting package. broke immediately. valdi doesn't use the dom. it doesn't use react's reconciler. your favorite react libraries are useless here.
that's the trade. pure native performance, but you're starting from scratch. no ecosystem. no stack overflow answers from 2019.
The problem isn't the technology. it's the timing. valdi launches into a world already split between react native and flutter. the javascript developers are comfortable. the dart developers are defensive.
and now snapchat says: "here's a third way."
i watched a youtube stream where four developers tried to bootstrap a project. they struggled with the cli. the docs assumed you knew how snapchat's internal teams work. one guy spent twenty minutes looking for the right import path.
this is the real barrier. not the class components. not the cmake requirement. it's that this was born inside a corporation and now has to learn how to live outside.
my first attempt at adding a custom native module was hilarious. i followed their guide. got a c++ file, an objective-c++ wrapper, and a typescript definition that disagreed with both. the compiler errors were in three languages. i gave up and had a beer.
and yet. the parts that work are so smooth. the performance is real. the debugging in vscode feels proper. you can set breakpoints in typescript and step into the c++ layout engine. that's insane.
i once named a side project "aspen" because i liked the tree. it had nothing to do with the code. just sounded nice. big companies can't do that. they need code names that sound like viking warriors.
valdi apparently started as an internal project called "screenshop." which is actually descriptive. rare. usually it's names like "project fenrir" or "hercules." something that looks good in an all-hands slide.
snapchat's engineers probably had t-shirts made. they probably have inside jokes about the rendering pipeline that we'll never understand. that's what happens when you work on something for eight years. it becomes your secret language.
now they're trying to teach it to us. and we're all speaking with accents.
look, most people don't need this.
if you're a solo dev with an app idea, use flutter. use react native. use whatever gets you to the app store fastest. valdi is overkill for your coffee shop loyalty app.
if your team is small and your timeline is short, the lack of libraries will murder you. you'll spend weeks rebuilding things you could npm install.
but if you're snapchat? if you have hundreds of engineers and a billion users and performance is measured in milliseconds? then yeah. you build valdi.
the biggest misconception is that this is a react native killer. it's not. it's a proof of concept that escaped the lab. it's snap saying "here's how we solved our problem." your problem is probably different.
i'm not switching my side project to valdi. it's too much. but i'm glad it exists. it shows the webview emperor has no clothes. it proves you can have typescript and native performance without the bridge tax.
i still think about that sunday. should have walked my dog instead of fighting expo. but at least now i know why my app felt wrong.
it's not me. it's the bridge.
valdi just made me realize we've been settling. and maybe that's the most annoying part of all.
Enjoyed this article? Check out more posts.
View All Posts