Skip to content
Mobile
Skill

/unistyles-v2-to-v3-migration

Migrate react-native-unistyles from v2 to v3. Triggers on: "migrate unistyles", "upgrade unistyles", "v2 to v3", "unistyles migration", "update unistyles", "convert unistyles v2". Covers all API changes including StyleSheet.create, useStyles removal, theme configuration,

From plugin
react-native-unistyles
3k2 skills

Claude Code

$ npx -y skills add jpudysz/react-native-unistyles --skill unistyles-v2-to-v3-migration --agent claude-code

SKILL.md

unistyles-v2-to-v3-migration.SKILL.md
name: unistyles-v2-to-v3-migration
description: >
  Migrate react-native-unistyles from v2 to v3. Triggers on: "migrate unistyles",
  "upgrade unistyles", "v2 to v3", "unistyles migration", "update unistyles",
  "convert unistyles v2". Covers all API changes including StyleSheet.create,
  useStyles removal, theme configuration, variants, withUnistyles, Babel plugin setup,
  style spreading fixes, and third-party component wrapping.
disable-model-invocation: false
user-invocable: true
allowed-tools: Read, Grep, Glob, Edit, Write, Bash(npx *)

Unistyles v2 to v3 Migration Skill

You are migrating a React Native codebase from react-native-unistyles v2 to v3. Follow this workflow precisely. v3 is a complete rewrite with C++ core (Nitro Modules), no re-renders, and a Babel plugin that processes StyleSheets at build time.

Prerequisites

  • React Native 0.85.0+ with New Architecture **mandatory** (the only architecture since RN 0.82)
  • React 19+ (enforced at runtime by Unistyles)
  • `react-native-nitro-modules` (native bridge dependency; Unistyles 3.4.0+ requires 0.37.1+)
  • `react-native-edge-to-edge` is not needed (optional since v3.1.0, now deprecated) — set `edgeToEdgeEnabled=true` in `android/gradle.properties` instead (Expo SDK 54+ enables it automatically)
  • Expo SDK 56+ (if using Expo; not compatible with Expo Go — requires dev client or prebuild)
  • Xcode 16.4+ (iOS, required by Nitro Modules), iOS 15.1+

Migration Workflow

Follow these steps IN ORDER. Each step must be completed before moving to the next.

Step 1: Install v3 and configure Babel plugin

Install v3 together with Nitro Modules, then rebuild the native app (pods / Gradle):

yarn add react-native-unistyles@3 react-native-nitro-modules@0.37.1  # or npm / bun / pnpm

Add the Babel plugin:

// babel.config.js
module.exports = {
  plugins: [
    ['react-native-unistyles/plugin', { root: 'src' }]  // your app source root
  ]
}

The `root` option is REQUIRED (the plugin throws without it, and it can't resolve to the project root itself). Every file under `root` is processed, no matter what it imports. Outside `root`, a file is processed only if it imports `react-native-unistyles`, contains an import listed in `autoProcessImports`, or matches `autoProcessPaths` (which always includes the two `react-native-reanimated` component paths; yours are added to them). `node_modules` is ignored unless whitelisted via `autoProcessPaths` / `autoRemapImports`.

If using React Compiler, the Unistyles plugin MUST come BEFORE React Compiler in the plugins array.

Since 3.6.0, Metro apps can use the experimental zero-config Metro integration instead: `module.exports = withUnistylesConfig(getDefaultConfig(__dirname))` with `withUnistylesConfig` from `react-native-unistyles/metro`, and no Unistyles entry in `babel.config.js` (having both throws). It needs no `root`/`autoProcess*` options, covers `node_modules` and tracks StyleSheet dependencies at runtime (no Babel transform). With it, `useVariants` must use the returned styles: `const variantStyles = styles.useVariants({ size })`. The Babel plugin stays the default.

If the app is bundled with Re.Pack, don't add the plugin to `babel.config.js` — use `RepackUnistylePlugin` from `react-native-unistyles/repack-plugin` with `unistylesPluginOptions: { root: 'src' }` instead.

Step 2: Replace UnistylesRegistry with StyleSheet.configure

- import { UnistylesRegistry } from 'react-native-unistyles'
+ import { StyleSheet } from 'react-native-unistyles'

- UnistylesRegistry
-   .addThemes({ light: lightTheme, dark: darkTheme })
-   .addBreakpoints({ sm: 0, md: 768, lg: 1200 })
-   .addConfig({
-     adaptiveThemes: true,
-     initialTheme: 'dark',
-     plugins: [myPlugin],
-     experimentalCSSMediaQueries: true,
-     windowResizeDebounceTimeMs: 100,
-     disableAnimatedInsets: true
-   })
+ StyleSheet.configure({
+   themes: { light: lightTheme, dark: darkTheme },
+   breakpoints: { sm: 0, md: 768, lg: 1200 },
+   settings: {
+     adaptiveThemes: true // OR initialTheme: 'dark' - never both
+   }
+ })

**Removed settings:** `plugins`, `experimentalCSSMediaQueries` (now always on), `windowResizeDebounceTimeMs` (no debounce), `disableAnimatedInsets` (insets no longer re-render).

**v3 `settings` accepts exactly:** `adaptiveThemes`, `initialTheme`, `CSSVars` (web), `nativeBreakpointsMode` (`'pixels'` default | `'points'`). Any other key throws. `initialTheme` together with `adaptiveThemes: true` throws (mutually exclusive), `adaptiveThemes` requires both `light` and `dark` themes, and the first breakpoint must be `0`. Call `StyleSheet.configure` before any `StyleSheet.create` is evaluated (import the config file first in your entry point).

Step 3: Replace all StyleSheet imports and createStyleSheet

Unistyles `StyleSheet` is a full polyfill of React Native's `StyleSheet` — it includes `hairlineWidth`, `compose`, `flatten`, `absoluteFill`, and `absoluteFillObject`. You should replace **all** `import { StyleSheet } from 'react-native'` with `import { StyleSheet } from 'react-native-unistyles'` so you have a single import.

- import { StyleSheet } from 'react-native'
- import { createStyleSheet } from 'react-native-unistyles'
+ import { StyleSheet } from 'react-native-unistyles'

- const stylesheet = createStyleSheet(theme => ({
+ const styles = StyleSheet.create(theme => ({
    container: {
      backgroundColor: theme.colors.background
    }
  }))

Step 4: Remove all useStyles hooks

- import { useStyles } from 'react-native-unistyles'

  const MyComponent = () => {
-   const { styles, theme } = useStyles(stylesheet)
    return <View style={styles.container} />
  }

Styles created with `StyleSheet.create` are used directly - no hook needed. The Babel plugin handles reactivity at build time.

Dynamic functions (`styles.box(width, color)`) keep working, but their arguments must be serializable (strings, numbers, boolean

Read more
@jpudysz
Ships withreact-native-unistyles

Level up your React Native StyleSheet

Stars on GitHub

Momentum

stars in total
3.0k
Star history of jpudysz/react-native-unistyles on GitHub, a chart by star-history.com

Other skills on react-native-unistyles.

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo2d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens2w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about unistyles-v2-to-v3-migration.

Which coding agents can use unistyles-v2-to-v3-migration?
unistyles-v2-to-v3-migration installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.