# ReactUnity: React components rendered straight into Unity without a DOM

> ReactUnity is an MIT licensed TypeScript project that renders React components directly into Unity, covering UGUI, UIToolkit and Editor windows, with no DOM and no embedded browser, laying out with a subset of CSS on top of Yoga flexbox. It suits a Unity team that wants to write its UI in TypeScript with React, Redux and react-router, and it needs a JavaScript engine inside the player to run it.

**ReactUnity/core** — React and HTML framework for Unity UI & UIToolkit

- Repository: https://github.com/ReactUnity/core
- Website: https://reactunity.github.io/
- Stars: 902 · Forks: 54
- Language: TypeScript
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/reactunity-core

## No DOM, no embedded browser, one React tree for three Unity targets

ReactUnity renders React components directly into Unity, covering UGUI, UIToolkit and Editor windows, with no DOM and no embedded browser.

That single sentence is the whole pitch and the whole technical bet. The usual way to put a React UI in a game is to run a web view, which means shipping a browser engine, accepting its weight, and living with a second rendering path that does not share anything with the game's own graphics. ReactUnity takes the other route: it implements a react-reconciler host config, which is the interface React uses to talk to a renderer, and points it at Unity's own UI systems.

The npm package table names the pieces. @reactunity/renderer is the react-reconciler host config along with generated type models. @reactunity/scripts is the build and dev-server toolchain, published as react-unity-scripts. @reactunity/material is a set of Material Design components. @reactunity/create is the project scaffolder, run as npx @reactunity/create.

On the Unity side, com.reactunity.core is the renderer, styling engine and Unity-side runtime. The other three packages are scripting engines, and the README's advice on them is specific: pick exactly one scripting engine so your project pulls in only one native binary. com.reactunity.quickjs is QuickJS and is marked Recommended. com.reactunity.jint is the Jint engine, described as pure C#, slower, no native binary. com.reactunity.clearscript is ClearScript, which is V8.

That choice is not cosmetic. A Unity player that has to interpret JavaScript at runtime has to carry an interpreter, and each engine has a different cost profile: a native binary to ship and to support per platform, a slower pure C# interpreter, or V8, which is the largest and the fastest. The renderer is engine-agnostic, which is why the engine is a separate package.

The runtime requirements table is small. Unity 2021.3 or newer, with CI covering 6000.0 and 6000.1. Node 20 or newer, used only while developing and not needed at runtime or in a built player. And TextMeshPro v3.

## Styling is a CSS subset on top of Yoga flexbox

The layout model is where the differences from the web become concrete, and it is the part most likely to surprise someone porting an existing React interface.

You lay things out with a subset of CSS on top of Yoga flexbox. Yoga is the flexbox layout engine that React Native uses, so the layout model is flexbox rather than the block-and-inline model of the browser, and the CSS you can use is a subset rather than the full language.

The consequence is that this is not a drop-in for a web UI. Flexbox means the flex properties work as you expect, and the direction and wrapping model is the one you already know from React Native, but anything that depends on the browser's own layout behaviours, tables, floats, or the finer points of the cascade, is not in scope. The styling engine is part of com.reactunity.core, and the documentation site is where the supported subset is specified.

The reason to accept that restriction is the rest of the design. The point of a reconciler host config is that React's model, its components, its hooks and its ecosystem all keep working, so you can use TypeScript, Redux, react-router, i18next and the rest, and only the leaf nodes that actually draw pixels are Unity objects. The layout engine sits underneath that, and it does the work the browser would otherwise do.

The three rendering targets share that model. UGUI is Unity's built-in UI system, UIToolkit is its newer retained-mode UI, and Editor windows let the same React code be used in Unity's own editor tooling, which is a genuinely useful case for a studio that wants one component library for both the game and the in-house tools.

The documentation site covers styling, the component reference and the scripting engines in depth, and the README says the documentation coverage is the weakest part of the project, which is a fair signal about where to look before committing.

## Two registries, one version number, and orphan branches

The packaging is unusual and worth understanding before you install anything, because it explains a URL that otherwise looks wrong.

The repository publishes to two registries. The Unity packages go to OpenUPM and as git tags, and the npm packages go to npm. Everything shares a single version number, so an upgrade moves both sides at once, which is the correct behaviour for a project where the renderer and the React app have to agree on a protocol.

The git URL that the README gives for Unity's package manager is a case in point:

```
https://github.com/ReactUnity/core.git#latest
```

It resolves even though the sources now live under unity/core/, because Unity packages are published to an orphan branch per package whose tree root is the package. The same trick is used for kitchen-sink/, which ships on its own branch with its file: and workspace: dependencies rewritten to published versions, so that the branch clones as a project that opens on its own.

That is a clever solution with a cost. A consumer adding a git URL dependency is pulling an orphan branch, and the version that branch points at is not visible from the branch name. It works, and it keeps the OpenUPM and git paths pointing at the same artefact, but it does mean that pinning a specific version means pinning a specific tag rather than a range, and it means the repository's layout and its published layout differ in a way that is not obvious from the outside.

The repository layout itself is a monorepo with unity/ for the Unity packages, packages/ for the npm packages, docs/ for the documentation site deployed to reactunity.github.io, kitchen-sink/ for a complete Unity project using ReactUnity published standalone, samples/ for smaller standalone samples, tests/ for the Unity project that runs the C# test suite, scripts/ for release tooling and media/ for logos and brand assets.

The kitchen-sink project is worth calling out, because it is the reference implementation. A complete Unity project that uses ReactUnity, published on its own branch so it can be cloned and opened, is the fastest way to see how the pieces fit together before wiring it into your own project.

## Getting a first React component onto a Unity canvas

The getting-started path has two halves, a Unity side and a React side, and the README's four steps cover both.

First the packages. They can be added via OpenUPM with a single command:

```bash
npx openupm-cli add com.reactunity.core com.reactunity.quickjs
```

or through Unity's package manager using the git URL shown earlier. Note that the OpenUPM command adds both the core package and the QuickJS engine, which follows the one-engine rule.

Then, inside the Unity project, the sequence is: create a canvas and add a ReactRendererUGUI component to it, run npx @reactunity/create@latest in the project root to scaffold the React side, run npm install and npm start from the generated React project, and press play in Unity.

The ReactRendererUGUI component is the anchor point. The renderer needs a target to render into, the canvas provides the surface, and the component carries the configuration for the host config to draw into it. The scaffolded React project then talks to the running editor over the dev server, and the same code path works in a built player.

The text rendering requirement deserves a note because it is easy to trip over. TextMeshPro v3 is listed as a requirement, which is a constraint on the Unity project rather than on the React code, and a project that has settled on a different text stack will have to reconcile that before anything renders.

The sample project, the kitchen-sink/ directory in the repository, is the fastest way to see the whole thing working with the four steps already done for you, and the samples/ directory holds smaller standalone examples for a single feature.

## Building the repository: pnpm workspaces, Biome and a headless Unity driver

Working on ReactUnity itself is a different set of requirements from consuming it, and the README is careful to separate the two.

Building the repository needs Node 26, pinned in .node-version, and pnpm 11, with the exact version coming from the packageManager field. The package.json confirms both, with the packageManager set to pnpm@11.25.0 and the engines field requiring node >=26. The floors in the requirements table, Unity 2021.3 and Node 20, are for consuming ReactUnity, not for building it.

The three commands are:

```bash
pnpm install
pnpm build
pnpm check
```

build compiles the npm packages in dependency order, and check runs Biome over the repository, which is what CI enforces. The package.json shows the same scripts, with build wired as pnpm -r --filter "./packages/*" run build, and lint, format and check all delegating to biome.

Working on a single package uses a filter, for example:

```bash
pnpm --filter @reactunity/renderer build
```

and running the kitchen-sink React app against a live Unity editor is a filtered start:

```bash
pnpm --filter reactunity-kitchen-sink start
```

Unity connects to that dev server and hot-reloads, so the edit loop does not require a player build.

The C# side has its own driver. The Unity project that runs the C# test suite lives in tests/, and the package.json shows the headless driver as node scripts/unity/cli.mts, with commands for compile, test and open, plus a bridge for talking to an Editor that is already open. The README notes that the Test Runner window and the Unity Tests workflow still work, and that the workflow is the only one that runs the full editor matrix.

Two build scripts in the package.json describe the unusual parts of the build. One rebuilds the Sucrase bundle that the Unity test runner evaluates inside QuickJS, and one rebuilds the vendored ExCSS.dll from a fork checked out as the vendor/excss submodule, which needs a dotnet SDK. Both results are committed, which is why a normal build does not need a dotnet SDK at all. The repository layout confirms this with vendor/ and native/ directories at the top level.

## Licence, cadence and what the merged history means for upgrades

The licence arrangement is split, and the split is between code and documentation. The project is MIT, with the LICENSE file at the root, and the documentation under docs/ is CC-BY-4.0, with its own file at docs/LICENSE.md. For a studio shipping a game, the MIT grant on the runtime means there is no obligation to open-source the game, and the CC licence on the documentation means the docs can be reused with attribution.

On cadence, the repository is not archived and the last push was on 2026-10-16, on the main branch. The releases are frequent and share a version number across both registries: reactunity@0.26.0 from 2026-09-29, reactunity@0.25.0 from 2026-09-15 and reactunity@0.24.0 from 2026-09-11. Three releases in under three weeks, with a version line that is still below 1.0.

The pre-1.0 version number is worth taking seriously rather than as a formality. A framework that renders a React tree into a game engine has a lot of surface where a minor change can affect your app, and the shared version number means you cannot upgrade only one side. When you do upgrade, the Unity packages and the npm packages move together, and your React application has to move with them.

The history of the repository also tells you something about its stability as a dependency. The README says ReactUnity used to be spread across a dozen repositories, and that they were merged here with their histories intact, so git log reaches back through every one of them. For a user, the practical benefit is that the project now has one issue tracker, one release train and one place to look, instead of twelve. For a user pinning a version, the practical cost is that older tags refer to a different repository structure, and the orphan-branch publishing scheme means the mapping between a version and a directory layout is not always obvious from the outside.

The CHANGELOG.md at the root and the documentation site are the two places to read before an upgrade, and CLAUDE.md is said to document the architecture and the toolchain decisions in more detail than the README does.

## Conclusion

ReactUnity fits a Unity team with web-trained engineers who want React, TypeScript, Redux and react-router in the game client, provided they can accept shipping a JavaScript engine in the build and restrict their styling to the supported CSS subset. It is the wrong choice for a project that needs the full CSS feature set, since only a subset is implemented, and the wrong choice for a team that wants zero runtime overhead, since the player must carry an interpreter and the React reconciler. Before you adopt it, read the styling and component reference on the documentation site, check that the TextMeshPro v3 requirement matches your project, and note that the packages publish to two registries under a single version number, so an upgrade moves the Unity side and the React side together.

## FAQ

### How do I install ReactUnity in a Unity project?

Add the packages via OpenUPM with `npx openupm-cli add com.reactunity.core com.reactunity.quickjs`, or add the git URL through Unity's package manager. Then create a canvas with a ReactRendererUGUI component, run `npx @reactunity/create@latest` to scaffold the React side, run npm install and npm start, and press play in Unity.

### Which scripting engine should I use with ReactUnity?

The README says to pick exactly one scripting engine so your project pulls in only one native binary. com.reactunity.quickjs is recommended, com.reactunity.jint is pure C# but slower, and com.reactunity.clearscript is ClearScript, which is V8.

### Does ReactUnity need a DOM or an embedded browser?

No. The README states that ReactUnity renders React components directly into Unity, UGUI, UIToolkit and Editor windows, with no DOM and no embedded browser. Layout is handled by a subset of CSS on top of Yoga flexbox.

### What are the requirements for using ReactUnity?

Unity 2021.3 or newer, with CI covering 6000.0 and 6000.1, Node 20 or newer but only for development since it is not needed at runtime or in a built player, and TextMeshPro v3.

### How is the ReactUnity repository built and tested?

Building it needs Node 26 and pnpm 11, with `pnpm install`, `pnpm build` and `pnpm check` for Biome. The C# side is driven headlessly by `pnpm unity`, with compile, test and open commands, and the test project lives in tests/.

## Sources

- [License: MIT](https://github.com/ReactUnity/core/blob/main/LICENSE)
- [Project website](https://reactunity.github.io/)
- [ReactUnity/core on GitHub](https://github.com/ReactUnity/core)
- [README](https://github.com/ReactUnity/core/blob/main/README.md)
- [Releases](https://github.com/ReactUnity/core/releases)

---

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