PiTyUs.Hire me

Assets & UI

Patterns for talking between NUI and Lua

Proven patterns for FiveM NUI communication: the action/data message convention, NUI callbacks with RegisterNuiCallback and fetch, request/response flows through the server, pushing state vs pulling it, throttling updates, focus handling, and validating everything the UI sends.

Updated 10 min readBy PiTyUs · FiveM developer

Overview

Every NUI resource has the same plumbing: Lua sends data to the page, the page asks Lua to do things, and anything that matters goes on to the server. Getting that plumbing right — one message convention, one callback helper, validation on the server — keeps complex UIs like phones and inventories maintainable.

The request/response flow

client.lualua
RegisterNuiCallback('bank:transfer', function(data, cb)
    if type(data.to) ~= 'number' or type(data.amount) ~= 'number' then
        return cb({ ok = false, error = 'invalid' })
    end
    local result = lib.callback.await('bank:transfer', false, data.to, data.amount)
    cb(result)
end)
server.lualua
lib.callback.register('bank:transfer', function(source, to, amount)
    -- validate target, amount limits, balance; then move money
    return { ok = true }
end)

The page sees one fetch that resolves with the server’s answer. Details: NUI callbacks and callbacks explained.

Push vs pull

DataPattern
Opening a menuPush everything the UI needs in one open message
Balance, job, inventory changesPush when it changes (framework events, state bags)
Speed, fuel, healthPoll a few times per second in Lua; send on change
Rarely needed detailsPull with a callback when the user opens them

Focus and lifecycle

  • SetNuiFocus(true, true) on open; SetNuiFocus(false, false) on every close path and on resource stop.
  • A close callback from the page (Escape key) so Lua can release focus.
  • Details: NUI focus and cursor.

Structuring bigger UIs

Type message payloads once and share them between Lua docs and the frontend; keep the Lua layer thin (validation and forwarding) and put business rules on the server. A React structure that follows these patterns: React NUI boilerplate.

Security

Players can call NUI callbacks from the devtools with any data. Treat callback input like any client input: validate types in Lua and re-check everything on the server — see secure server events.

Frequently asked questions

How should NUI and Lua exchange data?

Lua sends { action, data } messages with SendNUIMessage; the page calls Lua through NUI callbacks with fetch.

How does NUI get data from the server?

The NUI callback in Lua calls a server callback (for example lib.callback.await) and returns the result with cb.

Should my HUD poll values every frame?

No — poll a few times per second in Lua and send only changes.

Are NUI callbacks secure?

No more than any client input; validate on the server.

Need this built, not just explained?

Ten years of FiveM work, from Lua to NUI

Custom resources, React NUI, ESX / QBCore / Qbox integration, OneSync performance audits and security reviews — plus the websites and SEO around your server brand.

Related guides