NUI basics: building interfaces for FiveM
Declare a page with ui_page and list its files under files in the fxmanifest. Lua sends data with SendNUIMessage({...}), which arrives in the page as a message event with the table in event.data. The page talks back through NUI callbacks (fetch to https://<resource>/<name>), and SetNuiFocus gives it keyboard and mouse. Files are addressed as https://cfx-nui-<resource>/path.
Every modern FiveM interface — inventories, phones, HUDs, menus, loading screens — is a web page. FiveM embeds a Chromium browser (CEF) on top of the game, and each resource can show its own page there. That page is called NUI. If you can write HTML, CSS and JavaScript, you can build FiveM UI.

#Declaring the page
fx_version 'cerulean'
game 'gta5'
ui_page 'html/index.html'
files {
'html/index.html',
'html/style.css',
'html/app.js',
'html/img/*.png',
}
client_script 'client.lua'Every file the page loads must be listed in files, or it is not sent to players and the browser gets a 404. Wildcards work. A built React/Vite app is listed the same way — see React and Vite.
#Sending data to the page
RegisterCommand('bank', function()
SendNUIMessage({ action = 'open', balance = 12500 })
SetNuiFocus(true, true)
end, false)window.addEventListener('message', (event) => {
const msg = event.data;
if (msg.action === 'open') {
document.querySelector('#balance').textContent = '$' + msg.balance;
document.body.classList.add('open');
}
});The Lua table is converted to JSON and arrives as a plain JavaScript object. Use one field (like action) to route messages.
#Talking back to Lua
The page answers with a POST request to its resource; Lua handles it with RegisterNuiCallback. Full details and a reusable helper: NUI callbacks with fetch. Keyboard and mouse control: NUI focus and cursor.
#Asset URLs
| Reference | Use |
|---|---|
img/logo.png (relative) | Files in your own resource |
https://cfx-nui-ox_inventory/web/images/water.png | Files from another resource |
nui://resource/path | Older scheme, deprecated — prefer cfx-nui |
https://… | External hosting (CDN, remote images) |
#NUI page vs loading screen
| `ui_page` | `loadscreen` | |
|---|---|---|
| Shown | In game, whenever you display it | While the player joins |
| Talks to Lua | Messages and callbacks | Only receives loading events and handover data |
| Focus | SetNuiFocus | loadscreen_cursor for the mouse |
Loading screens are covered in the HTML loading screen tutorial.
#Plain HTML or a framework?
Plain HTML and JavaScript are perfect for small UIs. For inventories, phones or anything with lots of state, a framework (React, Vue, Svelte) built to static files keeps the code manageable. Either way the result is static files in files — nothing runs on a Node server.
Questions
What is NUI in FiveM?
Why does my NUI page not show?
ui_page path wrong, files missing from files, the resource not restarted, or the page hidden by CSS. Check the devtools console.How do I send data from Lua to NUI?
SendNUIMessage({...}) and listen for the message event in the page; the table arrives as event.data.Can I use React for FiveM NUI?
ui_page at the built index.html and list the build output in files.How do I load an image from another resource?
https://cfx-nui-<resource>/<path> — the file must be in that resource’s files.Ready to pick a map?
Twelve themes on three base map styles, $8 each, instant download.
Relevant to what you just read
The tool for this
A drag-and-drop loading screen, hosted for you From Free, built in the browser, exported as a drop-in resource.
Look it up while you work
The reference tables this guide leans on, free and without an account.
- The map modding glossary38 terms — file formats, radar parts, framework words — each with a one-line answer first.