About fivem-react-nui
A React and Vite skill for building FiveM NUI interfaces, aimed at developers using React 18, TypeScript, and Tailwind CSS. It documents CEF rendering constraints, Lua communication, and interface structure.
Key features
- 01Sets conventions for a React and Vite stack
- 02Describes two-way NUI and Lua communication
- 03Covers visibility and input focus management
- 04Lists FiveM CEF styling and performance constraints
Use cases
- 01Build a React NUI interface for FiveM
- 02Receive Lua messages and send NUI callbacks
- 03Investigate CEF styling or asset caching issues
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ proelias7/ fivem-skill --skill fivem-react-nuiAfter installing, type/fivem-react-nuiin Claude Code to confirm it loaded.
Bundled filesui-guide.md
Details
From the project READMEFiveM NUI — React + Vite
Language rule: Internal reasoning is in compact English. All messages and output displayed to the user must be in the user's language.
Stack: React 18 + TypeScript + Vite + Tailwind CSS v3.4.17 + Zustand
Fundamental Rules
base: "./"invite.config.ts— MANDATORY for assets to load in FiveM- Never fix Vite
rollupOptions.outputfilenames without[hash]— FiveM CEF caches NUI; fixed names (assets/[name].css) leave stale CSS for some players - Overlay/shell fill on transparent html: opaque hex +
background-image: linear-gradient(#111,#111)— neverrgba()/ Tailwindbg-*/70/opacityon the same rounded element as the panel fill (CEF bug on some iGPUs). Screen dim = sibling layer withoutborder-radius(::beforeinset-0). Toggle withdisplay: flex|none— never jQueryfadeIn/fadeOuton the overlay container - Background missing / border rendering defect with
border-style: solid: try top/leftinsetand bottom/rightoutseton the affected element; see the directional border fallback inui-guide.md§6. Verify visually in FiveM CEF; do not replace solid borders globally. - Use
remfor ALL sizes — NEVERpxfor layout (scales with player resolution) - Tailwind v4 uses OKLCH, which FiveM CEF does not support — use Tailwind v3.4.17
- FORBIDDEN:
backdrop-filter: blur(),filter: blur(),filter: drop-shadow()— cause FPS drop - FORBIDDEN: framer-motion, GSAP, react-spring — use pure CSS transitions/keyframes
- Global
overflow: hiddenanduser-select: none - Independent modules (Notify, Progress, HUD) outside
VisibilityProvider - Main interface (panels, crafts, dialogs) inside
VisibilityProviderwithSetNuiFocus isEnvBrowser()for data mocking in dev- Communication:
observe()to listen to NUI messages,Post.create()to send callbacks
Architecture
// main.tsx
ReactDOM.createRoot(document.getElementById("root")!).render(
<ThemeProvider>
{/* Always visible — do not block game input */}
<NotifyComponent />
<ProgressComponent />
{/* Controlled by VisibilityProvider — requires NuiFocus */}
<HashRouter>
<VisibilityProvider>
<AppContent />
</VisibilityProvider>
</HashRouter>
</ThemeProvider>
);
NUI Hooks
observe — Listen to Lua messages
observe<NotifyData>("module:notify", (data) => {
addNotify(data);
});
Post — Send callbacks to Lua
await Post.create("buy", { item: "water", qty: 1 });
Lua side
-- Open
SendNUIMessage({ action = "setNui", nui = "panel", data = { ... } })
SetNuiFocus(true, true)
-- Close callback
RegisterNUICallback("removeFocus", function(data, cb)
SetNuiFocus(false, false)
cb("ok")
end)
fxmanifest.lua Integration
ui_page "src/ui/build/index.html"
files {
"src/ui/build/index.html",
"src/ui/build/**/*", -- covers index-[hash].js/css
"src/ui/project/public/**/*",
}
Recommended Dependencies
{
"dependencies": {
"react": "^18", "react-dom": "^18",
"react-router-dom": "^7", "zustand": "^4",
"clsx": "^2", "tailwind-merge": "^3",
"lucide-react": "^0.5", "tailwindcss": "^3",
"autoprefixer": "^10", "postcss": "^8"
},
"devDependencies": {
"@vitejs/plugin-react-swc": "^3",
"typescript": "^5", "vite": "^5"
}
}
Avoid: MUI, Chakra UI, Ant Design, framer-motion, styled-components — all too heavy for FiveM CEF.
fxmind agent vision (NUI dump)
Prefer structured state over screenshots. The agent wires and unwires — do not ask the user to patch scripts:
fxmind_fivem_nui_wire{ resource }— patches fxmanifest + injects DOM probe intoui_pageensurebridge + resource; user opens NUI in-gamefxmind_fivem_nui_dumpfxmind_fivem_nui_unwirebefore finishing (mandatory cleanup)
Optional permanent integration (not required for agent debug): registerFxmindNuiDump(() => useStore.getState()) from bridge snippets.
For the full implementation guide (project structure, vite.config, responsive system, CSS restrictions, hooks source, Visibility/Animation/Theme providers, debugger): ui-guide.md