Migrate a React Native project from NativeWind to Uniwind. Use when the user wants to replace NativeWind with Uniwind, upgrade from NativeWind, switch to Uniwind, or mentions NativeWind-to-Uniwind migration. Handles package removal, config migration, Tailwind 4 upgrade, cssInterop removal, theme conversion, and all breaking changes.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Migrate a React Native project from NativeWind to Uniwind. Use when the user wants to replace NativeWind with Uniwind, upgrade from NativeWind, switch to Uniwind, or mentions NativeWind-to-Uniwind migration. Handles package removal, config migration, Tailwind 4 upgrade, cssInterop removal, theme conversion, and all breaking changes.
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:
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.
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:
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.
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<ButtoncolorClassName="accent-background"title="Press me"
/>// tintColor prop → tintColorClassName with accent- prefix<ImageclassName="w-6 h-6"tintColorClassName="accent-red-500"source={icon}
/>
Rule: className accepts any Tailwind utility for style-based props. For non-style props (color, tintColor, etc.), use {propName}ClassName with the accent- prefix. This applies to all built-in React Native components.
IMPORTANT: All theme variants must define the exact same set of CSS variables. If light defines --color-primary and --color-typography, then dark (and any custom theme) must also define both. Mismatched variables will cause a Uniwind runtime error.
No ThemeProvider wrapper needed. Remove the NativeWind <ThemeProvider> or vars() wrapper from JSX. Keep React Navigation's <ThemeProvider> if used.
If the project used nested theme wrappers to preview or force a theme for a specific subtree (for example a demo card, settings preview, or side-by-side theme comparison), use Uniwind Pro's ScopedTheme instead of changing the global theme:
NativeWind uses 14px as the base rem, Uniwind defaults to 16px. Step 4 already sets polyfills: { rem: 14 } in metro config to preserve NativeWind's spacing. If the user explicitly wants Uniwind's default (16px), they can remove the polyfill — but warn them that all spacing/sizing will shift.
Step 13: Handle className Deduplication
Uniwind does NOT auto-deduplicate conflicting classNames (NativeWind did). If your codebase relies on override patterns like className={`p-4 ${overrideClass}`}, set up a cn utility.
First, check if the project already has a cn helper (common in shadcn/ui projects):
rg "export function cn|export const cn" -g "*.{ts,tsx,js}"
If it exists, keep it as-is. If not, install dependencies and create it:
npm install tailwind-merge clsx
Create lib/cn.ts (or wherever utils live in the project):
Use cn instead of raw twMerge — it handles conditional classes, arrays, and falsy values via clsx before deduplicating with tailwind-merge.
Important utilities are also supported in Uniwind. If migrated NativeWind code intentionally forces an override with Tailwind's important modifier, keep it:
Important utilities override non-important utilities for the same style property. Inline style still has the highest priority, even over important className utilities.
Step 14: Update Animated Class Names
If the project used NativeWind animated-* / transition class patterns, migrate those to explicit react-native-reanimated usage. Uniwind OSS does not provide NativeWind-style animated class behavior.
Use this migration guide section as the source of truth:
import { useUniwind } from'uniwind';
const { theme, hasAdaptiveThemes } = useUniwind();
// theme: current theme name — "light", "dark", "system", or custom// hasAdaptiveThemes: true if app follows system color scheme
Use for: displaying theme name in UI, conditional rendering by theme, side effects on theme change.
Uniwind Static API — Theme Access (no re-render)
Access theme info without causing re-renders:
import { Uniwind } from'uniwind';
Uniwind.currentTheme// "light", "dark", "system", or customUniwind.hasAdaptiveThemes// true if following system color scheme
Use for: logging, analytics, imperative logic outside render.
useResolveClassNames — Convert classNames to Style Objects
Converts Tailwind classes into React Native style objects. Use when working with components that don't support className and can't be wrapped with withUniwind (e.g. react-navigation theme config):
Define custom utilities using device-aware CSS functions like hairlineWidth(), fontScale(), pixelRatio(). These can be used everywhere (custom CSS classes, @utility, etc.) — but NOT inside @theme {} (which only accepts static values). Use @utility to create reusable Tailwind-style classes:
By default Uniwind follows the system color scheme (adaptive themes). To switch themes programmatically:
import { Uniwind } from'uniwind';
Uniwind.setTheme('dark'); // force darkUniwind.setTheme('light'); // force lightUniwind.setTheme('system'); // follow system (default)Uniwind.setTheme('ocean'); // custom theme (must be in extraThemes)
Use ScopedTheme when the project needs a different theme for only part of the UI (component previews, themed sections, nested demos) without changing the app-wide theme:
Update theme variables at runtime, e.g. based on user preferences or API responses:
import { Uniwind } from'uniwind';
// Preconfigure theme based on user input or API responseUniwind.updateCSSVariables('light', {
'--color-primary': '#ff6600',
'--color-background': '#1a1a2e',
});
This pattern should be used only when the app has real runtime theming needs (for example, user-selected brand colors or API-driven themes).
If the project is a monorepo, add @source directives in global.css so Tailwind scans packages outside the CSS entry file's directory (only if that directory has components with Tailwind classes):
Custom Fonts: Uniwind maps className to font-family only — font files must be loaded separately (expo-font plugin in app.json or react-native-asset for bare RN). Font family names in @theme must exactly match filenames (without extension). Use @variant for per-platform fonts (must be inside @layer theme { :root { } }):
global.css Location in Expo Router: Place at project root and import in root layout (app/_layout.tsx). If placed in app/, components outside need @source directives. Tailwind scans from global.css location.
Full App Reloads on CSS Changes: Metro can't hot-reload files with many providers. Move global.css import deeper in the component tree (e.g. navigation root or home screen) to fix.
Gradients: Built-in support, no extra deps needed. Use bg-gradient-to-r from-red-500 via-yellow-500 to-green-500. For expo-linear-gradient, use useCSSVariable to get colors — withUniwind won't work since gradient props are arrays.
Style Specificity: Inline style always overrides className. Use className for static styles, inline only for truly dynamic values. Avoid mixing both for the same property.
Safe Area Classes: p-safe, pt-safe, pb-safe, px-safe, py-safe, m-safe, mt-safe, etc. Also supports -or-{value} (min spacing) and -offset-{value} (extra spacing) variants.
Next.js: Not officially supported. Uniwind is for Metro and Vite. Community plugin: uniwind-plugin-next. For Next.js, use standard Tailwind CSS and share design tokens.
Vite: Supported since v1.2.0. Use uniwind/vite plugin alongside @tailwindcss/vite.
UI Kits: HeroUI Native, react-native-reusables and Gluestack 4.1+ works great with Uniwind
Known Issues & Gotchas
data- attributes*: Uniwind supports data-[prop=value]:utility syntax for conditional styling, similar to NativeWind.
Animated styles: Migrate NativeWind animated classes to react-native-reanimated directly. Uniwind Pro has built-in Reanimated support.
Verification
After migration, verify:
npx react-native start --reset-cache (clear Metro cache) or with expo npx expo start -c
All screens render correctly on iOS and Android
Theme switching works (light/dark)
Custom fonts load correctly
Safe area insets apply properly
No console warnings about missing styles
No remaining imports from nativewind or react-native-css-interop
IMPORTANT: Do NOT guess Uniwind APIs. If you are unsure about any Uniwind API, hook, component, or configuration option, fetch and verify against the official docs: https://docs.uniwind.dev/llms-full.txt