Creator playbook Guide

FiveM NUI tutorial: a minimal panel, messages and close callback

Build a small FiveM NUI panel with a resource manifest, HTML, browser messages and a Lua close callback. Diagnose blank UI, missing assets and focus problems.

FiveM NUI tutorial: a minimal panel, messages and close callback — original Magnate explanatory diagram Original explanatory diagram · Not game footage

Define the resource and its UI assets

This original example is for current FiveM/GTA V development. It is not a GTA VI compatibility claim and has not been run inside a FiveM session. Use the resource-manifest tutorial first if resource folders and client scripts are unfamiliar.

Create client.lua at the resource root and an ui folder containing index.html and main.js. The Cfx fullscreen NUI guide explains that the root HTML page is declared with ui_page and that its client assets also need file declarations. Keep the paths aligned with the files you actually create.

fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
client_script 'client.lua'
ui_page 'ui/index.html'
files { 'ui/index.html', 'ui/main.js' }

Keep the panel hidden until the game opens it

Put the HTML below in ui/index.html. It starts hidden so connecting to the resource does not immediately cover the game. A plain button and a visible status message make the close path easy to inspect before adding styling or a larger application.

The page loads main.js from the same UI folder. If you later split out a stylesheet, font or image, declare that asset as well. A working standalone HTML page does not prove every file is included in the FiveM resource pack.

ui/index.html
<!doctype html>
<html lang="en"><meta charset="utf-8"><title>Magnate NUI example</title>
<body><section id="panel" hidden><h1>Development panel</h1><button id="close">Close</button><p id="status" role="status"></p></section><script src="main.js"></script></body></html>

Receive a message and send an acknowledged close request

Put this script in ui/main.js. It accepts only the example’s visibility message with a boolean open value. The panel changes state in response to that message; the close button sends a request to the resource’s close callback.

The Cfx callback reference uses the resource name supplied by GetParentResourceName and a JSON POST body. This code checks the HTTP response and acknowledgment, then reports failures as text. Do not copy the callback URL into a normal website expecting it to behave like an ordinary public API.

ui/main.js — original browser-side example
const panel = document.querySelector('#panel');
const status = document.querySelector('#status');
window.addEventListener('message', ({ data }) => {
  if (data && data.type === 'magnate:visibility' && typeof data.open === 'boolean') {
    panel.hidden = !data.open;
    status.textContent = '';
  }
});
document.querySelector('#close').addEventListener('click', async () => {
  try {
    const response = await fetch(`https://${GetParentResourceName()}/close`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json; charset=UTF-8' },
      body: JSON.stringify({})
    });
    if (!response.ok) throw new Error('Close request failed');
    const result = await response.json();
    if (!result.ok) throw new Error('Close was not acknowledged');
  } catch {
    status.textContent = 'Could not close the panel. Check the resource callback.';
  }
});

Open the panel and release focus on close

Put the Lua example in client.lua. The magnatepanel command requests focus and sends the visibility message. The close callback releases focus, tells the UI to hide and returns an acknowledgment. Returning data matters: Cfx warns that omitted callback responses cause requests to stall.

Use the callback API documented for your installed artifact and confirm it registers without an error. Start with this small example before integrating a framework menu. The resource-stop handler releases focus only when this resource stops. Verify that cleanup during a restart while the panel is open in your development environment.

client.lua — command and close callback
RegisterCommand('magnatepanel', function()
  SetNuiFocus(true, true)
  SendNUIMessage({ type = 'magnate:visibility', open = true })
end, false)

RegisterNuiCallback('close', function(data, cb)
  SetNuiFocus(false, false)
  SendNUIMessage({ type = 'magnate:visibility', open = false })
  cb({ ok = true })
end)

AddEventHandler('onClientResourceStop', function(resourceName)
  if resourceName == GetCurrentResourceName() then
    SetNuiFocus(false, false)
  end
end)

Trace one boundary at a time

For the joining screen, use the loading-screen tutorial: its lifecycle differs from this in-game panel. A blank panel and a stuck cursor are different failures. Inspect resource loading, browser asset loading, message delivery and the return callback separately. Record the console error and the step that caused it instead of changing every file at once.

In your own FiveM development session, test opening, closing, repeated opening and resource restart while open. Verify both visual state and keyboard/mouse behavior. This checklist describes required integration testing; the site build cannot substitute for those in-game checks.

NUI troubleshooting sequence
SymptomFirst inspection
Blank UIui_page path, file declarations and browser asset errors
Message ignoredMessage type and boolean open value
Close fetch failsResource name, callback registration and response
Cursor stays capturedFocus release and resource lifecycle cleanup
Works in a normal browser onlyFiveM callback environment and packaged asset paths

Questions, answered.

Can I test the whole callback in a normal web browser?

A normal browser can render HTML, but the example’s resource callback environment comes from FiveM. It does not prove in-game integration.

Do NUI callbacks need a response?

Yes. Cfx documentation requires returning callback data so the browser request can complete.

Sources & editorial notes

Source review: October 6, 2026. Platform announcements can change. This guide separates published facts from Magnate’s original analysis and preparation advice.

  1. Cfx — Fullscreen NUI Official UI page, assets, messages and focus documentation.
  2. Cfx — NUI callbacks Official callback registration and JSON response guidance.
  3. Cfx — Resource manifest Official manifest metadata and file declarations.
  4. Cfx — onClientResourceStop Official stopped-resource name and client lifecycle event.

Published by an independent editorial brand. Read our editorial standards.

Find your next move

Search the Magnate guide library.

Browse every guide