← Writing
Engineering

Notes from three weeks building mobile with Expo

I have spent about three weeks building a mobile app with Expo, React Native and NativeWind for a work project. I come from years of doing web. A few notes from the process.

1. The same code runs on iOS, Android and web

This is not marketing. With Expo Router, React Native Web and NativeWind you can keep a single codebase that compiles to all three targets. There are cases where you reach for Platform.select() or .native.tsx / .web.tsx files, but 80 to 90% of the code is shared without touching it.

The strange thing is how little this gets discussed. My feed is full of React Native vs Flutter and Expo vs bare workflow, but barely anyone talks about this. For a small team that needs all three targets, the savings are real.

2. NativeWind makes Tailwind work in React Native

I expected friction and there was none. Tailwind classes compile to native StyleSheet. className replaces style, and if you come from Tailwind on the web the learning curve is basically zero.

The catch is that some utilities have no native equivalent. Anything that depends on DOM-specific CSS is simply out. It is documented, but you want to know it going in.

3. The real pain is the version ecosystem

Here is where the honeymoon ends. Each Expo SDK pins specific versions of React Native, React and native libraries. If you want a third-party library, you have to check it is compatible with your SDK. Upgrading from one SDK to the next means reviewing breaking changes in a cascade: Expo, React Native, the native libs, and sometimes NativeWind.

It is not Expo's fault. It is the nature of the mobile ecosystem. But coming from web, where npm update is almost always safe, it is a real mental shift. Every upgrade is a decision, not a routine.

If you come from web and need mobile, this stack lowers the barrier a lot. The curve is fast until you hit the version system, where reading changelogs becomes part of the daily job.