# Unistyles 3 moves the stylesheet into C++ and the peer dependency into Nitro

> The React Native styling library rebuilt its core as shared C++ over JSI, made Nitro Modules a required install, and lists the reason your styles update without a re-render.

**jpudysz/react-native-unistyles** — Level up your React Native StyleSheet

- Repository: https://github.com/jpudysz/react-native-unistyles
- Website: https://unistyl.es
- Stars: 2,956 · Forks: 133
- Language: TypeScript
- License: not declared
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/jpudysz-react-native-unistyles

## Two installs, and the second one is not optional

Installation is two commands, and the ordering in the README makes it clear that they are not interchangeable:

```shell
yarn add react-native-unistyles
```

then the dependency:

```shell
yarn add react-native-nitro-modules
```

Nitro Modules is a hard requirement in v3, which is a real change from earlier versions and the single most common source of confusion when upgrading. The README does not treat it as a soft peer dependency you might skip; the whole architecture is built on it, so a missing install is a missing runtime rather than a degraded feature.

What the README does provide is a compatibility table, which is more useful than it looks because the acceptable Nitro version moves with the Unistyles version:

| react-native-unistyles | Minimum react-native-nitro-modules |
|------------------------|--------------------------------------|
| >= 3.0.0               | >= 0.33.9                            |
| >= 3.1.0               | >= 0.35.0                            |
| >= 3.2.0               | >= 0.35.2                            |

The direction of travel is upward on both sides, so an app pinned to an old Nitro cannot simply take the newest Unistyles. That table is the thing to check when an install fails to link.

## What a shared C++ core buys you

The feature list is short and each item maps to a mechanism. A shared core with C++ and JSI bindings means the same compiled code runs on both platforms rather than two implementations drifting apart. Powered by Nitro Modules is what makes that core installable and callable from JavaScript without a bridge. Tight integration with Fabric and Shadow Tree is the part that matters for behaviour, because the shadow tree is the structure React Native uses to describe what should be on screen.

From there, no re-renders follows as a consequence rather than a promise. If a style change can be applied by writing into the shadow tree, there is no state change in React to trigger a render, so a component whose only prop is a colour does not re-run when that colour changes. The feature list also claims the addition costs under 0.1 ms per StyleSheet, which is a per-call overhead figure rather than a benchmark of anything, but it is at least the right dimension to quote since it describes what your component pays.

Two features are about not taking over your app. It does not introduce new components, so the view hierarchy stays clean and there is no wrapper element in your tree. And it registers multiple themes, changing between them with a single function call, which matters for apps with light and dark modes or for design tokens that swap wholesale.

The web story is its own line in the list: a custom web parser, plus custom classes and pseudo-classes. Rather than compiling to CSS text and hoping the browser agrees, the stylesheet is parsed on the web side too, so class and pseudo-class names behave the way you wrote them. Topics list react-native-web alongside macOS and Windows, so the same library is expected to serve all of them.

## The monorepo runs on Bun and keeps a skills directory

The repository root is a Bun workspace with two globs:

```
"workspaces": [
  "packages/*",
  "apps/*"
]
```

That matches the tree, which holds `packages/`, `apps/`, `assets/`, `bun.lock`, `bunfig.toml` and `skills/` alongside the usual configuration. The root manifest is named react-native-unistyles-monorepo and is marked private, which is what you would expect of a workspace root rather than a published package.

The scripts are all thin wrappers that delegate into one package:

```
"lint": "bun run --cwd packages/unistyles lint",
"test": "bun run --cwd packages/unistyles test",
"tsc": "bun run --cwd packages/unistyles tsc",
```

Every check runs with `bun run --cwd`, which tells you the actual library lives in `packages/unistyles` and everything else at the root is plumbing. The toolchain fields are explicit: `packageManager` is bun@1.3.2 and `engines` requires node >= 20.18.0.

Two entries at the root are less expected. `.oxfmtrc.json` and `.oxlintrc.json` mean the maintainer formats and lints with Oxfmt and Oxlint rather than Prettier and ESLint, and `.husky/` plus a `prepare` script that runs husky means git hooks install themselves. The `skills/` directory is the most unusual thing here, since a styling library shipping a skills directory suggests the project is also meant to be consumed by tooling rather than only by application code.

None of this affects an app that installs the package. Your bundler does not care that the maintainer develops in Bun, but it does tell you the project has a fairly heavy internal setup, which is worth knowing if you plan to open a pull request.

## Edge to edge is now your decision on Android

Since v3.1.0, `react-native-edge-to-edge` is an optional dependency. The README recommends setting `edgeToEdgeEnabled=true` in `android/gradle.properties`, and gives three reasons: it enforces translucent system bars on modals, it disables legacy StatusBar hacks, and it enables additional React Native core fixes. Expo SDK 54 and later set it automatically.

The last sentence of that note is the practical guidance. You can still install `react-native-edge-to-edge` for ecosystem compatibility, specifically for libraries like react-native-bootsplash and react-native-permissions, so the recommendation is not to remove it but to stop requiring it. That split matters because edge-to-edge handling is exactly the kind of setting where two libraries disagreeing about who owns the status bar produces a bug that looks like a layout problem and is not one.

If you are on Expo 54 or newer, this section is mostly informational. If you are on a bare React Native project, the gradle property is a line you add rather than a decision you deliberate on, and the legacy behaviour you are opting out of is precisely the thing that makes translucent bars on modals render incorrectly.

## Recent releases read like a bug list for variants and themes

The published tags give a good sense of where the work is. v3.2.4 on 2026-04-24 upgraded Nitro and fixed two specific behaviours: platform colour inside variants not working, and components wrapped in `withUnistyles` not following a scoped theme. Both are the kind of fix that only appears once real applications use the library, since a scoped theme and a platform-aware variant are each plausible on their own and interact badly in combination.

v3.2.5 on 2026-05-27 moved the Expo example to SDK 56 and React Native 0.85.3, upgraded Nitro again, and added support for all key casings in variants. Key casing in a variant is a small thing that a user notices immediately when it is wrong, since a selector that should match silently does not.

v3.3.0 on 2026-07-10 is the most interesting of the three. It parses `transformOrigin` strings for shadow tree updates, adds native prop parsing for background images on Android only, and upgrades Nitro to 0.36.1. The first of those is the architecture showing through: if `transformOrigin` arrives as a string from CSS-style input, someone has to parse it, and if the parsed result is pushed into the shadow tree rather than into React state, no re-render is needed. The Android-only qualifier on background images is the sort of asymmetry that the shared C++ core makes possible, and also the sort of thing you would want to check before assuming web behaves the same.

The last push was 2026-08-13, after v3.3.0 shipped, so there is unreleased work in progress. The project has 2,956 stars, 133 forks and 54 open issues, and the documentation site at unistyl.es carries versioned paths such as v3 for the starter, the migration guide from 2.0, a page on how Unistyles works, the API reference and an examples section.

## The licence badge and the licence field disagree

The README carries a MIT licence badge, and a per-repository licence field would normally agree with it. Here it does not: the licence field is empty while the badge points at the MIT text. One of the two is out of date, and it is not clear which.

This is worth resolving before you depend on the library rather than after, because the MIT badge is a rendering of a claim and the missing field is a claim about metadata that some tooling reads directly. In practice the fix is a quick look at the repository's licence file and, if you need certainty for a commercial product, a check with your own legal reader. It is also the sort of gap that appears in projects where the maintainer has not touched licensing since an early commit, which is unremarkable and still worth ten seconds of attention.

Everything else about the project's status is straightforward. The author is jpudysz, the description is Level up your React Native StyleSheet, the homepage is unistyl.es, and the language is TypeScript. The topics list includes expo, react, react-native, typescript, react-native-web, react-native-macos and react-native-windows, which is the same seven-platform claim the badge row at the top of the README makes in icon form.

One claim in the feature list deserves a caveat rather than a repetition. Share up to 100% of your styles across platforms in monorepo is a ceiling, not a typical outcome, and it holds only where the styles are genuinely platform-independent, since anything using platform-specific props or a web-only selector stops being shareable. Treat it as an upper bound when you are deciding whether a shared design system is worth attempting across an app, its web build and its desktop builds.

## Conclusion

The architectural bet in Unistyles 3 is that a style update should never be a React render, and every design decision follows from that. If a stylesheet can be compiled, shared and pushed into the shadow tree directly, then theme changes, variant matching and responsive breakpoints all stop being render triggers, and the difference between a smooth screen and a janky one comes down to whether that path exists. The cost is a native dependency you cannot defer: Nitro Modules is a mandatory install, the acceptable version depends on which Unistyles you take, and Android users get a recommendation to flip edgeToEdgeEnabled in gradle.properties or accept the legacy StatusBar behaviour. Two details are worth checking before you adopt it. The repository's licence field is empty even though the README carries an MIT badge, so confirm the terms in the repository itself rather than trusting the badge. And the library's own development runs on Bun through a monorepo of packages and apps, which tells you nothing about what your app needs, since the published package is consumed by a Metro bundler like any other React Native dependency.

## FAQ

### Do I need to install anything besides Unistyles?

Yes. Unistyles 3 requires react-native-nitro-modules as a peer dependency, so a project that installs only react-native-unistyles will not link. The minimum acceptable Nitro version depends on your Unistyles version, and the README carries a table mapping each range, from 0.33.9 for 3.0.0 upward.

### Does Unistyles cause re-renders when styles change?

That is the central design goal rather than a side effect. Because styles are compiled into a shared C++ core and pushed into the shadow tree, a style update does not go through React state, so components do not re-render because a style changed. This is why the library depends on Nitro Modules and integrates with Fabric rather than replacing StyleSheet at the JavaScript level.

### What is the edge-to-edge requirement on Android?

Since v3.1.0, react-native-edge-to-edge is optional. The README recommends setting `edgeToEdgeEnabled=true` in `android/gradle.properties`, which enforces translucent system bars on modals, disables legacy StatusBar hacks and enables additional core fixes. Expo SDK 54 and later enable it automatically. You can still install the package for libraries such as react-native-bootsplash and react-native-permissions.

### Can I share styles between iOS, Android and web?

Up to a point. The feature list claims you can share up to 100% of your styles across platforms in a monorepo, and the web implementation has its own parser with custom classes and pseudo-classes rather than compiling to CSS text. Styles that use platform-specific properties or web-only selectors stop being shareable, so treat the 100% figure as a ceiling rather than a typical result.

### How do I migrate from Unistyles 2 to version 3?

There is a dedicated migration guide in the documentation, published under the v3 path along with a getting-started page and a page explaining how Unistyles works internally. The main structural change to plan for is the Nitro Modules requirement, since v3 does not run without it, and the optional edge-to-edge dependency from 3.1.0 onward.

## Sources

- [Issues](https://github.com/jpudysz/react-native-unistyles/issues)
- [jpudysz/react-native-unistyles on GitHub](https://github.com/jpudysz/react-native-unistyles)
- [Project website](https://unistyl.es)
- [README](https://github.com/jpudysz/react-native-unistyles/blob/main/README.md)
- [Releases](https://github.com/jpudysz/react-native-unistyles/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jpudysz-react-native-unistyles
