If you've tried to set up NativeWind (Tailwind CSS for React Native) in a new React Native project recently, you've likely run into a wall of cryptic errors involving the Metro bundler, the new require context, and missing modules. The rapid evolution of the React Native ecosystem post-0.72, especially with the shift towards a more "web-aligned" build system, has broken many older guides.
After much trial and error, I've found a specific combination of package versions that works together perfectly. This setup will get you from zero to styled in minutes, not hours.
The Problem
After React Native 0.72, the introduction of the New Architecture by default and changes to how Metro handles assets broke the standard tailwindcss setup. Common errors include:
Unable to resolve module 'react-native-safe-area-context'- Issues with the
require.contextin thetailwind.config.jsfile. - Metro bundler failures when trying to compile the Tailwind CSS.
The Solution: A Version-Locked, Battle-Tested Stack
The key is using versions of nativewind and tailwindcss that are compatible with the latest React Native build system, along with the crucial, updated native dependencies.
Here is the magic combination:
"dependencies": {
"nativewind": "4.1.23",
"tailwindcss": "3.4.17",
"react-native-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "^4.12.0"
}
Let's set it up step-by-step.
Step-by-Step Setup Guide
Step 1: Create a New React Native Project
Start with a fresh project. I'll assume you're using the new "Compact" default template.
npx react-native@latest init MyWindApp
cd MyWindApp
Step 2: Install the Perfect Package Combo
This is the most critical step. Run this install command to get the exact versions we need.
npm install nativewind@4.1.23 tailwindcss@3.4.17 react-native-native-reanimated@~3.16.1 react-native-safe-area-context@^4.12.0
-
nativewind@4.1.23: This specific version is stable and avoids the compatibility issues present in some newer alpha/beta releases. -
tailwindcss@3.4.17: A stable, feature-complete version of Tailwind that works seamlessly with the NativeWind plugin. -
react-native-safe-area-context: This is a required peer dependency for NativeWind to handle safe areas. Explicitly installing the latest stable version ensures it's present. -
react-native-native-reanimated: While not always a direct dependency for basic NativeWind, many modern RN libraries use it, and having it installed preemptively prevents a very common class of errors.
Step 3: Configure Tailwind CSS
- Generate your
tailwind.config.jsfile.
npx tailwindcss init
- Update the generated
tailwind.config.jsfile. The critical part is configuring thecontentpaths so Tailwind can find your React Native components and purge unused styles.
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
// Important: Use `.native` for React Native
content: ["./app/**/*.{js,jsx,ts,tsx}", "./src/**/*.{js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},
plugins: [],
}
Step 4: Configure Metro & Babel
We need to tell Metro to process the CSS files that NativeWind will generate.
- Run
metro config initor Create ametro.config.jsfile or run in your project root if it doesn't exist, and add the following configuration:
// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require('nativewind/metro');
const config = getDefaultConfig(__dirname);
// This is the important part: Wrap the default config with NativeWind
module.exports = withNativeWind(config, { input: './global.css' });
Note: If you aren't using Expo, you can often use const { getDefaultConfig } = require("metro-config");.
- Update your
babel.config.jsto include the NativeWind Babel plugin.
// babel.config.js
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
// Add this line
'nativewind/babel',
],
};
Step 5: Create Your Global CSS File
Create a file called global.css in your project root. This is where your Tailwind directives will live.
/* global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Step 6: Import the CSS and Apply the Provider
Finally, we need to import the CSS and wrap our app with the NativeWindProvider.
Open your App.tsx (or App.jsx) and modify it as follows:
// App.tsx
import React from 'react';
// 1. Import the CSS and the Provider
import { NativeWindProvider } from "nativewind";
import './global.css'; // Import the CSS file
// Your main App component
function App() {
return (
// 2. Wrap your app with the NativeWindProvider
// note: not required to wrap and use native-wind-provider
<NativeWindProvider>
{/* Your existing app code starts here */}
<View className="flex-1 items-center justify-center bg-white">
<Text className="text-4xl font-bold text-blue-500">Hello, NativeWind!</Text>
<StatusBar style="auto" />
</View>
</NativeWindProvider>
);
}
export default App;
You're All Set! 🚀
That's it! Now you can use Tailwind's intuitive utility classes directly in your React Native components using the className prop.
Run your project:
npm run android
# or
npm run ios
You should see your beautifully styled "Hello, NativeWind!" text.
Troubleshooting Tips
-
Cache Clear: If things look weird, always clear your Metro cache:
npm start -- --reset-cache - Restart Metro/Bundler: After installing new native dependencies, fully stop and restart your Metro bundler.
-
Check Versions: Double-check your
package.jsonto ensure the versions match exactly. A single mismatched package can break the entire setup.
This combination of nativewind@4.1.23 and tailwindcss@3.4.17 has proven to be incredibly stable across multiple projects. It bypasses the current ecosystem growing pains and lets you focus on what's important: building a great app.
I hope this saves you hours of frustration. Happy coding!
Follow me on Linkedin aramoh3ni
Top comments (0)