uni-stack/uniwind1 file

Migrate Nativewind To Uniwind

>

Specification
Skill ID
uni-stack/uniwind/migrate-nativewind-to-uniwind
Publisher
uni-stack
Repository
uniwind
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

uni-stack/uniwind/migrate-nativewind-to-uniwindInstalls these files
  • SKILL.md

What this skill tells the agent

Migrate NativeWind to Uniwind

Uniwind replaces NativeWind with better performance and stability. It requires Tailwind CSS 4 and uses CSS-based theming instead of JS config.

Pre-Migration Checklist

Before starting, read the project's existing config files to understand the current setup:

  • package.json (NativeWind version, dependencies)
  • tailwind.config.js / tailwind.config.ts
  • metro.config.js
  • babel.config.js
  • global.css or equivalent CSS entry file
  • nativewind-env.d.ts or nativewind.d.ts
  • Any file using cssInterop or remapProps from nativewind
  • Any file importing from react-native-css-interop
  • Any ThemeProvider from NativeWind (vars() usage)

Step 1: Remove NativeWind and Related Packages

Uninstall ALL of these packages (if present):

npm uninstall nativewind react-native-css-interop
# or
yarn remove nativewind react-native-css-interop
# or
bun remove nativewind react-native-css-interop

CRITICAL: react-native-css-interop is a NativeWind dependency that must be removed. It is commonly missed during migration. Search the entire codebase for any imports from it:

rg "react-native-css-interop" -g "*.{ts,tsx,js,jsx}"

Remove every import and usage found.

Step 2: Install Uniwind and Tailwind 4

npm install uniwind tailwindcss@latest
# or
yarn add uniwind tailwindcss@latest
# or
bun add uniwind tailwindcss@latest

Ensure tailwindcss is version 4+.

Step 3: Update babel.config.js

Remove the NativeWind babel preset:

// REMOVE this line from presets array:
// 'nativewind/babel'

No Uniwind babel preset is needed.

Step 4: Update metro.config.js

Replace NativeWind's metro config with Uniwind's. withUniwindConfig must be the outermost wrapper.

Before (NativeWind):

const { withNativeWind } = require('nativewind/metro');
module.exports = withNativeWind(config, { input: './global.css' });

After (Uniwind):

const { getDefaultConfig } = require('expo/metro-config');
// For bare RN: const { getDefaultConfig } = require('@react-native/metro-config');
const { withUniwindConfig } = require('uniwind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withUniwindConfig(config, {
  cssEntryFile: './global.css',
  polyfills: { rem: 14 },
});

cssEntryFile must be a relative path string from project root (e.g. ./global.css or ./app/global.css). Do not use absolute paths or path.resolve(...) / path.join(...) for this option.

// ❌ Broken
cssEntryFile: path.resolve(__dirname, 'app', 'global.css')

// ✅ Correct
cssEntryFile: './app/global.css'

Always set `polyfills.rem` to 14 to match NativeWind's default rem value and prevent spacing/sizing differences after migration.

If the project uses custom themes beyond light/dark (e.g. defined via NativeWind's vars() or a custom ThemeProvider), register them with extraThemes. Do NOT include light or dark — they are added automatically:

module.exports = withUniwindConfig(config, {
  cssEntryFile: './global.css',
  polyfills: { rem: 14 },
  extraThemes: ['ocean', 'sunset', 'premium'],
});

Options:

  • cssEntryFile (required): relative path string to CSS entry file (from project root)
  • polyfills.rem (required for migration): set to 14 to match NativeWind's rem base
  • extraThemes (required if project has custom themes): array of custom theme names — do NOT include light/dark
  • dtsFile (optional): path for generated TypeScript types, defaults to ./uniwind-types.d.ts
  • debug (optional): log unsupported CSS properties during dev

Step 5: Update global.css

Replace NativeWind's Tailwind 3 directives with Tailwind 4 imports:

Before:

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

After:

@import 'tailwindcss';
@import 'uniwind';

Step 6: Update CSS Entry Import

Ensure global.css is imported in your main App component (e.g., App.tsx), NOT in the root index.ts/index.js where you register the app — importing there breaks hot reload.

Step 7: Delete NativeWind Type Definitions

Delete nativewind-env.d.ts or nativewind.d.ts. Uniwind auto-generates its own types at the path specified by dtsFile.

Step 8: Delete tailwind.config.js

Remove tailwind.config.js / tailwind.config.ts entirely. All theme config moves to CSS using Tailwind 4's @theme directive.

Migrate custom theme values to global.css:

Before (tailwind.config.js):

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: '#00a8ff',
        secondary: '#273c75',
      },
      fontFamily: {
        normal: ['Roboto-Regular'],
        bold: ['Roboto-Bold'],
      },
    },
  },
};

After (global.css):

@import 'tailwindcss';
@import 'uniwind';

@theme {
  --color-primary: #00a8ff;
  --color-secondary: #273c75;
  --font-normal: 'Roboto-Regular';
  --font-bold: 'Roboto-Bold';
}

Font families must specify a single font — React Native doesn't support font fallbacks.

Step 9: Remove ALL cssInterop and remapProps Usage

This is the most commonly missed step. Search the entire codebase:

rg "cssInterop|remapProps" -g "*.{ts,tsx,js,jsx}"

Replace every cssInterop() / remapProps() call with Uniwind's withUniwind():

Before (NativeWind):

import { cssInterop } from 'react-native-css-interop';
import { Image } from 'expo-image';

cssInterop(Image, { className: 'style' });

After (Uniwind):

import { withUniwind } from 'uniwind';
import { Image as ExpoImage } from 'expo-image';

export const Image = withUniwind(ExpoImage);

withUniwind automatically maps className → style and other common props. For custom prop mappings:

const StyledProgressBar = withUniwind(ProgressBar, {
  width: {
    fromClassName: 'widthClassName',
    styleProperty: 'width',
  },
});

Define wrapped components at module level (not inside render functions). Each component should only be wrapped once:

  • Used in one file only — define the wrapped component in that same file: ```tsx // screens/ProfileScreen.tsx import { withUniwind } from 'uniwind'; import { BlurView as RNBlurView } from '@react-native-community/blur';

const BlurView = withUniwind(RNBlurView);

export function ProfileScreen() { return <BlurView className="flex-1" />; }


- **Used across multiple files** — wrap once in a shared module and re-export:

// components/styled.ts import { withUniwind } from 'uniwind'; import { Image as ExpoImage } from 'expo-image'; import { LinearGradient as RNLinearGradient } from 'expo-linear-gradient';

export const Image = withUniwind(ExpoImage); export const LinearGradient = withUniwind(RNLinearGradient);

  Then import from the shared module everywhere:

import { Image, LinearGradient } from '@/components/styled';


Never call `withUniwind` on the same component in multiple files — wrap once, import everywhere.

**IMPORTANT**: Do NOT wrap components from `react-native` or `react-native-reanimated` with `withUniwind` — they already support `className` out of the box. This includes `View`, `Text`, `Image`, `ScrollView`, `FlatList`, `Pressable`, `TextInput`, `Animated.View`, etc. Only use `withUniwind` for **third-party** components (e.g. `expo-image`, `expo-linear-gradient`, `@react-native-community/blur`).

**IMPORTANT — accent- prefix for non-style color props**: React Native components have props like `color`, `tintColor`, `backgroundColor` that are NOT part of the `style` object. To set these via Tailwind classes, use the `accent-` prefix with the corresponding `*ClassName` prop:

// color prop → colorClassName with accent- prefix <ActivityIndicator className="m-4" size="large" colorClassName="accent-blue-500 dark:accent-blue-400" />

// color prop on Button <Button colorClassName="accent-background"

More from uni-stack

Use this skill in a project

Open any RiverX project, search the Skills panel for uni-stack/uniwind/migrate-nativewind-to-uniwind, and install it in one click.

Use this skill