React 19 for Roblox TypeScript. A full-featured UI layer built on the React Lua 17 runtime, extended with React 19 APIs, text-as-children, Tailwind-style
className, HTML element aliases, and a configurable styling system.
| Package | Description |
|---|---|
@nrbx/react |
Core React bindings: JSX, hooks, components, styling, HTML elements |
@nrbx/react-roblox |
Roblox renderer: createRoot, createPortal, flushSync |
@nrbx/react-tsconfig |
Shared TypeScript presets for @nrbx/react projects |
@nrbx/react-is |
Type-checking utilities for React elements |
@nrbx/react-globals |
React global flags and the DevTools hook |
@nrbx/react-devtools-core |
DevTools backend, vendored for Roblox |
@nrbx/react-devtools |
Connect to DevTools by importing this package |
@nrbx/react-debug-tools |
Hook inspection helpers for debugging |
@nrbx/react-builders |
Builder-style component construction and serialization |
@nrbx/scheduler |
Cooperative scheduler used by the reconciler |
npm install @nrbx/react @nrbx/react-roblox
# or
pnpm add @nrbx/react @nrbx/react-roblox
# or
yarn add @nrbx/react @nrbx/react-robloxAdd the package folders to your Rojo project file under node_modules:
"node_modules": {
"$className": "Folder",
"@nrbx": {
"$path": "node_modules/@nrbx"
},
"@rbxts": {
"$path": "node_modules/@rbxts"
},
"@rbxts-js": {
"$path": "node_modules/@rbxts-js"
}
}The simplest option is to extend the shared preset:
npm install @nrbx/react-tsconfig{
"extends": "@nrbx/react-tsconfig"
}Or configure JSX manually:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@nrbx/react",
"types": ["@rbxts/types"]
}
}import React, { useState } from "@nrbx/react";
import { createRoot } from "@nrbx/react-roblox";
function Counter() {
const [count, setCount] = useState(0);
return (
<textbutton
Text={`Count: ${count}`}
AnchorPoint={new Vector2(0.5, 0.5)}
Size={new UDim2(0, 120, 0, 50)}
Position={new UDim2(0.5, 0, 0.5, 0)}
Event={{ Activated: () => setCount(count + 1) }}
/>
);
}
const root = createRoot(script.Parent!.WaitForChild("ScreenGui") as ScreenGui);
root.render(<Counter />);- React 19 hooks —
useId,useTransition,useDeferredValue,useSyncExternalStore,useInsertionEffect,useOptimistic,useActionState,use, and more - Text as children — string and number children are automatically wrapped in
TextLabelinstances with transparent backgrounds - Tailwind-style
className— map utility classes likeflex,items-center,bg-blue-500, andw-32to Roblox GUI properties - HTML elements —
div,span,h1-h6,p,a,button,img,ul,li,form,input, and more - Class components —
Component,PureComponent, full lifecycle, and error boundaries - Configurable styling —
defineConfig()for custom colors, spacing, and theme defaults - DevTools support — connect the standalone DevTools app to inspect your component tree
The full wiki lives in docs/wiki:
To connect the standalone DevTools app, import the backend before React:
import ReactGlobals from "@nrbx/react-globals";
import { backend } from "@nrbx/react-devtools-core";
ReactGlobals.__DEV__ = true;
ReactGlobals.__PROFILE__ = true;
backend.connectToDevtools();MIT — see LICENSE.txt
Built with React concepts - roblox-ts - React Lua
This is a work-in-progress project. A lot of the documentation and jsDocs are written or have been re-written using AI (because i can write good code, but can't document for the life of me beyond minimum effort comments), so any comments and issues you may find, please just pull request with your amendments.
Part of this package was also made with AI assistance for sections where it was a bit rough or difficult to get around, if you don't like AI you can scream down my ear, but I am a single developer doing the work of a team, I could care less what you think, I wasn't going to work on this by myself and leave loads of holes and stuff which I'll probably never get back to doing.
