Troubleshooting NativeWind v4 in Expo
Always start here
- Restart Metro without cache:
npx expo start --clear- Confirm Tailwind CLI works independently of NativeWind:
npx tailwindcss --input ./global.css --output output.cssIf the class you expect is not present in output.css, your issue is Tailwind config/content, not NativeWind runtime.
Quick checks (90% of issues)
“className not applying” / everything looks unstyled
- Confirm
global.cssexists. - Confirm
metro.config.jswithNativeWind(..., { input: "./global.css" })points to it. - Confirm the entry component imports it exactly once.
- Confirm
tailwind.config.jscontentglobs include all files that containclassNamestrings:./App.{js,jsx,ts,tsx}./app/**/*.{js,jsx,ts,tsx}(Expo Router)./components/**/*.{js,jsx,ts,tsx}
- Clear cache and restart.
Web looks unstyled
- Confirm
app.jsonsets:expo.web.bundler = "metro"
Verify the NativeWind install from inside the app
NativeWind exposes a helper:
import { verifyInstallation } from "nativewind";
export default function App() {
verifyInstallation(); // call inside component scope, not globally
return null;
}Remove it after you confirm the setup.
Enable debug logs
Run your start command with DEBUG=nativewind:
DEBUG=nativewind npx expo start --clearCommon React Native gotchas (looks like “NativeWind is broken”)
Colour classes don’t “cascade”
React Native doesn’t cascade text colour from a <View> to a nested <Text>.
Move text-* classes onto the <Text> element.
Conditional styles
React Native can behave oddly when styles appear/disappear. Prefer explicit style pairs (both light + dark) rather than only setting one side.
Safe area utilities not working
- Inspect the actual native root and existing
SafeAreaProviderbefore adding one. - Expo Router supplies the usual route provider; do not duplicate it at that same root.
- A separate native root or modal boundary may need its own provider. Check the boundary and inset measurements on the target platforms rather than applying a universal ban on nested providers.
Expo Router breaks after adding babel/metro config
If the Router stops finding routes, confirm:
- Babel still uses
babel-preset-expoas the base preset. - You restarted with
npx expo start --clear.
If you see EXPO_ROUTER_APP_ROOT missing, consult Expo Router troubleshooting and ensure your entry point/babel config still matches Router expectations.