Home/Blog/How to Add Uniwind to a React Native Expo App

How to Add Uniwind to a React Native Expo App

May 30, 2026 · 5 min read

Introduction

Uniwind lets you use Tailwind-style utility classes in React Native and Expo apps. Instead of creating a StyleSheet for every small layout change, you can write concise className strings such as flex-1 items-center bg-white px-6. This is especially useful in Expo projects where you want fast iteration, shared design tokens, and code that feels familiar to web developers.

This guide walks through adding Uniwind to a React Native Expo app, configuring Metro and Tailwind, importing your global stylesheet, and using utility classes in real components.

Prerequisites

You should already have Node.js installed and be comfortable running Expo locally. The examples use an Expo app with TypeScript, but the setup is nearly the same for JavaScript projects.

node --version
npx expo --version

If you do not already have an Expo app, create one:

npx create-expo-app@latest uniwind-expo-app
cd uniwind-expo-app

Install Uniwind

Install Uniwind and the peer dependencies commonly required by Expo styling and animation tooling. Use expo install for React Native packages so Expo chooses compatible versions.

npm install uniwind tailwindcss
npx expo install react-native-reanimated react-native-safe-area-context

If your project uses Yarn or pnpm, use the equivalent command:

yarn add uniwind tailwindcss
npx expo install react-native-reanimated react-native-safe-area-context

# or
pnpm add uniwind tailwindcss
npx expo install react-native-reanimated react-native-safe-area-context

Create the Tailwind CSS Entry File

At the root of your project, create a global.css file. This file is the CSS entry point that Uniwind processes.

@tailwind base;
@tailwind components;
@tailwind utilities;

Keep this file small. Put Tailwind directives and project-wide CSS variables here. Component styling should usually stay in your React Native components through utility classes.

Create or Update Tailwind Configuration

Create a tailwind.config.js file if your project does not already have one.

npx tailwindcss init

Then configure Tailwind to scan your app files. Include every directory where React components live.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './App.{js,jsx,ts,tsx}',
    './app/**/*.{js,jsx,ts,tsx}',
    './src/**/*.{js,jsx,ts,tsx}',
    './components/**/*.{js,jsx,ts,tsx}',
  ],
  theme: {
    extend: {
      colors: {
        brand: {
          50: '#eef6ff',
          500: '#2563eb',
          700: '#1d4ed8',
        },
      },
    },
  },
  plugins: [],
};

The content list matters. If Tailwind cannot find your files, it cannot generate the utilities used by your components.

Configure Metro for Uniwind

Expo uses Metro to bundle your React Native app. Uniwind needs to hook into Metro so it can process your CSS entry file and make generated styles available to the native runtime.

Create or update metro.config.js in the project root:

const { getDefaultConfig } = require('expo/metro-config');
const { withUniwind } = require('uniwind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withUniwind(config, {
  // Path to the CSS file that contains @tailwind directives.
  input: './global.css',
});

If your installed Uniwind version uses a slightly different option name for the CSS entry file, keep the structure the same and follow the package documentation for that option. The important part is wrapping the Expo Metro config with withUniwind.

Configure Babel

Update babel.config.js so Uniwind can transform className usage correctly. If you use Reanimated, keep its plugin last.

module.exports = function (api) {
  api.cache(true);

  return {
    presets: ['babel-preset-expo'],
    plugins: [
      'uniwind/babel',

      // Keep this last when react-native-reanimated is installed.
      'react-native-reanimated/plugin',
    ],
  };
};

After changing Babel or Metro configuration, restart Expo with a cleared cache:

npx expo start -c

Import the Global Stylesheet

Import global.css once at the top level of your app.

If You Use Expo Router

Import it in app/_layout.tsx:

import '../global.css';

import { Stack } from 'expo-router';

export default function RootLayout() {
  return <Stack />;
}

If You Use a Single App Component

Import it in App.tsx:

import './global.css';

import { Text, View } from 'react-native';

export default function App() {
  return (
    <View className='flex-1 items-center justify-center bg-white px-6'>
      <Text className='text-2xl font-bold text-brand-700'>
        Hello Uniwind
      </Text>
    </View>
  );
}

Add TypeScript Support for className

React Native components do not include className in their default TypeScript types. Many Uniwind setups provide a type declaration file to enable it.

Create uniwind-env.d.ts or global.d.ts in the project root:

/// <reference types='uniwind/types' />

Make sure TypeScript includes declaration files. Most Expo TypeScript projects already do. If your tsconfig.json has a restrictive include list, add the declaration file.

{
  'extends': 'expo/tsconfig.base',
  'compilerOptions': {
    'strict': true
  },
  'include': [
    '**/*.ts',
    '**/*.tsx',
    '**/*.d.ts'
  ]
}

Build a Simple Styled Screen

Now you can write React Native UI with utility classes. Here is a small reusable card component.

import { Pressable, Text, View } from 'react-native';

type FeatureCardProps = {
  title: string;
  description: string;
  onPress?: () => void;
};

export function FeatureCard({ title, description, onPress }: FeatureCardProps) {
  return (
    <Pressable
      onPress={onPress}
      className='rounded-2xl border border-slate-200 bg-white p-5 shadow-sm active:opacity-80'
    >
      <Text className='text-lg font-semibold text-slate-950'>{title}</Text>

      <Text className='mt-2 text-sm leading-5 text-slate-600'>
        {description}
      </Text>
    </Pressable>
  );
}

export default function HomeScreen() {
  return (
    <View className='flex-1 bg-slate-50 px-5 pt-16'>
      <Text className='text-3xl font-bold tracking-tight text-slate-950'>
        Expo + Uniwind
      </Text>

      <Text className='mt-2 text-base text-slate-600'>
        Use Tailwind-style utilities in your React Native screens.
      </Text>

      <View className='mt-6 gap-4'>
        <FeatureCard
          title='Fast styling'
          description='Compose layouts directly in JSX with readable utility classes.'
        />

        <FeatureCard
          title='Shared tokens'
          description='Extend colors, spacing, and typography from tailwind.config.js.'
        />
      </View>
    </View>
  );
}

Using Conditional Classes

For conditional styling, keep class strings simple. You can use template literals or a helper such as clsx.

npm install clsx
import clsx from 'clsx';
import { Text, Pressable } from 'react-native';

type ButtonProps = {
  label: string;
  variant?: 'primary' | 'secondary';
};

export function Button({ label, variant = 'primary' }: ButtonProps) {
  return (
    <Pressable
      className={clsx(
        'rounded-xl px-4 py-3',
        variant === 'primary' && 'bg-brand-500',
        variant === 'secondary' && 'bg-slate-200'
      )}
    >
      <Text
        className={clsx(
          'text-center font-semibold',
          variant === 'primary' ? 'text-white' : 'text-slate-900'
        )}
      >
        {label}
      </Text>
    </Pressable>
  );
}

Common Troubleshooting

Utilities Are Not Applied

Check that global.css is imported once at the app root. Then confirm that metro.config.js wraps the config with withUniwind. Finally, make sure the file containing your component matches the content globs in tailwind.config.js.

TypeScript Says className Does Not Exist

Add the Uniwind type reference file and restart the TypeScript server in your editor. Also restart Expo if the app is already running.

Changes Do Not Show Up

Clear the Metro cache after changing Babel, Metro, Tailwind, or CSS entry configuration.

npx expo start -c

Reanimated Errors

If you installed Reanimated, ensure react-native-reanimated/plugin is the last Babel plugin. Then rebuild or restart the Expo development server.

Conclusion

Adding Uniwind to an Expo app requires four main steps: install the package, create a Tailwind CSS entry file, wire Uniwind into Metro and Babel, and import the stylesheet at the app root. After that, you can style React Native components with Tailwind-style utility classes while still keeping the native performance and workflow of Expo.

For a clean codebase, keep shared design values in tailwind.config.js, use small reusable components, and avoid long unreadable class strings. Uniwind works best when utility classes express layout clearly and your components remain focused on behavior.

Advertisement

You might also like