Interfaces: menus, inputs and NUI · Lesson 3/3 · 10 min

Your own NUI: when menus aren't enough

For HUDs, phones or shops with a custom design you need NUI: a web page (HTML/CSS/JS) on top of the game.

When you want an interface with your own design (a HUD, a phone, a nice-looking shop) you build a NUI: a web page that FiveM draws over the game. It works the same with QBCore as without it.

Declare it and open/close with focus

lua
-- fxmanifest.lua
ui_page 'html/index.html'
files { 'html/index.html', 'html/style.css', 'html/app.js' }

fxmanifest.lua

lua
-- client.lua
RegisterCommand('tienda', function()
  SetNuiFocus(true, true)                 -- give focus and mouse to the web page
  SendNUIMessage({ action = 'open' })
end)

RegisterNUICallback('close', function(_, cb)
  SetNuiFocus(false, false)               -- return control to the game!
  cb('ok')
end)

-- buy: the client only ASKS; the server decides
RegisterNUICallback('comprar', function(data, cb)
  QBCore.Functions.TriggerCallback('tienda:comprar', function(ok)
    cb({ ok = ok })
  end, data.item)
end)

client.lua

The #1 NUI bug: forgetting SetNuiFocus(false, false) on close leaves the player with the mouse out and unable to move. Always wire the close with ESC and via callback. And remember: the real purchase is validated on the SERVER (callback), never in the JS.

Practice what you learned

0/3
Test

Para abrir tu NUI y darle el ratón al jugador, ¿qué llamada necesitas?

Rellena los huecos

Completa la función nativa que manda datos desde Lua hacia la web (JS).

1({ action = 'open', data = { dinero = 500 } })
Pista

Lua → JS: la web escucha estos mensajes con un addEventListener('message').

Corrige el error

Este callback cierra la NUI pero deja al jugador atrapado sin poder moverse. Falta devolverle el control quitando el foco.

Este código tiene un fallo:

1RegisterNUICallback('close', function(_, cb)
2 cb('ok')
3end)

Reescríbelo corregido:

Pista

El bug nº1 de NUI: olvidar SetNuiFocus(false, false) al cerrar deja el ratón fuera y bloquea el movimiento.

Challenge: code it yourself

Create the skeleton of a NUI: fxmanifest with ui_page/files, open with /tienda giving focus, and a 'close' callback that removes it.

Write it yourself in your editor (VS Code) and test it on your server. You learn here by doing it, not by copying.

See hint

ui_page → /tienda opens with focus → JS listens for 'open' and shows; ESC does a fetch to 'close' that removes the focus.

Escribe aquí tu solución:

How was this lesson?