Installing Lumo UI
This guide covers QBCore, Qbox, ESX Legacy and standalone servers: what to install, what to remove, which files to change, and how to fix the resources that are affected. Read the part for your framework, then the troubleshooting table.
- What is in the download
- Before you start
- QBCore
- Qbox
- ESX Legacy
- Standalone
- After installing
- Troubleshooting
What is in the download
[lumo-ui]/
├── lumo-ui/ the product: HUD, notifications, target eye, radial,
│ context menu, input dialog, progress bar, text UI
├── lumo-interact/ walk-up "press E / hold G" prompts (drawn by lumo-ui)
├── lumo-chat-theme/ the Lumo look for FiveM's chat, plus /me
└── [compat]/ drop-in shims, each one its own resource
├── qb-target/ exports['qb-target']:* and exports.qtarget:*
├── qb-menu/ exports['qb-menu']:openMenu, qb-menu:client:openMenu
├── qb-input/ exports['qb-input']:ShowInput
├── qb-radialmenu/ exports['qb-radialmenu']:AddOption / RemoveOption
├── progressbar/ exports['progressbar']:Progress*, QBCore.Functions.Progressbar
├── esx_notify/ ESX.ShowNotification (ESX only)
├── esx_progressbar/ ESX.Progressbar (ESX only)
├── esx_textui/ ESX.TextUI / ESX.HideUI (ESX only)
└── lumo-hud-ui/ exports['lumo-hud-ui']:* (older Lumo scripts)A shim has the same name as the resource it replaces and forwards its exports and events to lumo-ui. Your other scripts keep calling exports['qb-target']:AddBoxZone(...) and never notice the change.
Two rules for shims:
- A shim and the original cannot both be in
resources/. FiveM loads only one of two resources with the same name, and you cannot choose which. For every shim you use, move the original folder out ofresources/(not just itsensureline). - Delete the shims you do not use from
[compat], for the same reason. For example, on QBCore deleteesx_notify,esx_progressbarandesx_textui; on ESX keepqb-targetonly if you use Lumo's target eye.
Do not ensure [lumo-ui] as a whole folder: ensure each resource by name, as shown below, so only the shims you chose start.
Before you start
Back up
resources/andserver.cfg.Requirements: oxmysql. Nothing else.
Make a folder nothing ensures, for example
resources/[disabled]/. The old resources go there, so you can put them back later.Put the
[lumo-ui]folder inresources/.Give your admins the
/uiadmin tab, inserver.cfg:cfgadd_ace group.admin lumo.ui.admin allowOn QBCore and Qbox the
godandadminpermissions also count, and on ESX theadmingroup (LumoUiConfig.AdminPermissionsinconfig.lua).
QBCore
Lumo UI replaces the whole qb-* interface layer.
1. Move these folders to [disabled]
| Old resource | Replaced by | Shim to ensure |
|---|---|---|
qb-hud | lumo-ui HUD | — |
qb-target (or qtarget) | lumo-ui target eye | qb-target |
qb-menu | lumo-ui context menu | qb-menu |
qb-input | lumo-ui input dialog | qb-input |
qb-radialmenu | lumo-ui radial | qb-radialmenu |
progressbar | lumo-ui progress bar | progressbar |
Also move any other HUD (ps-hud, jg-hud, …): two HUDs draw on top of each other. Keep PolyZone if other scripts use it; lumo-ui does not need it.
2. server.cfg
Right after qb-core (and before your jobs and other scripts):
cfg
ensure oxmysql
ensure qb-core
ensure lumo-ui
ensure lumo-interact
ensure lumo-chat-theme # after chat
ensure qb-target
ensure qb-menu
ensure qb-input
ensure qb-radialmenu
ensure progressbar3. Notifications (one edit in qb-core)
QBCore.Functions.Notify draws qb-core's own notification. To have lumo-ui draw it, open qb-core/client/functions.lua, find function QBCore.Functions.Notify(text, texttype, length, icon) and add these lines at the top of it:
lua
function QBCore.Functions.Notify(text, texttype, length, icon)
if GetResourceState('lumo-ui') == 'started' then
return exports['lumo-ui']:Notify(text, texttype, length, icon)
end
-- … the original code stays below …Server notifications (QBCore.Functions.Notify(source, …) on the server, TriggerClientEvent('QBCore:Notify', …)) end in the same function, so this one edit covers them. Re-apply it after updating qb-core.
4. Radial items
Copy the items from your old qb-radialmenu/config.lua into config.lua:
Config.MenuItems→LumoUiConfig.Radial.Items(same fields:id,title,icon,type,event,shouldClose,items).Config.JobInteractions→LumoUiConfig.Radial.JobItems, keyed by job name. They show in a "Work" submenu while on duty.
The seated vehicle menu (seats, engine, doors, extras) is built in; LumoUiConfig.Radial.VehicleMenu turns its parts on or off. Scripts that call exports['qb-radialmenu']:AddOption(...) keep working through the shim.
5. Affected resources
| Resource | What to do |
|---|---|
| qb-smallresources | Nothing. Its seatbelt and cruise events are read by the HUD. |
| qb-policejob, qb-ambulancejob, qb-mechanicjob, … | Nothing. They use qb-target, qb-menu, qb-input and progressbar through the shims. |
| Fuel (LegacyFuel, cdn-fuel, ps-fuel, lc_fuel, ox_fuel) | Nothing. Found automatically (LumoUiConfig.Hud.Fuel = 'auto'). |
Stress (hud:server:GainStress / RelieveStress) | Nothing. Same events and the same metadata.stress as qb-hud. |
Scripts using ox_lib's UI directly (lib.notify, lib.progressBar, lib.registerContext, lib.inputDialog) | ox_lib keeps drawing those. Lumo UI does not replace ox_lib. |
Qbox
Qbox is built on ox_lib and ox_target, and most qbx_* resources call them directly. Lumo UI does not replace ox_lib or ox_target: Qbox needs both. So on Qbox, Lumo UI gives you the HUD, the radial, Lumo notifications and the qb-* compatibility, and ox_target stays your target eye.
1. Move these folders to [disabled]
| Old resource | Replaced by |
|---|---|
qbx_hud (or qb-hud, ps-hud, any HUD) | lumo-ui HUD |
qbx_radialmenu (optional, see step 5) | lumo-ui radial |
Keep ox_lib and ox_target.
2. Turn off Lumo's target eye
ox_target and Lumo's eye both open on Left Alt. In lumo-ui/config.lua:
lua
LumoUiConfig.Target = {
Enabled = false,
-- …
}and delete [compat]/qb-target: ox_target already answers exports.qtarget:*. Scripts written only for exports['qb-target'] need their target calls changed to ox_target (most popular scripts have an ox_target option in their config).
3. server.cfg
cfg
ensure ox_lib
ensure oxmysql
ensure qbx_core
ensure ox_target
ensure lumo-ui
ensure lumo-interact
ensure lumo-chat-theme # after chat
# Only for older qb-* scripts that call these resources by name:
ensure qb-menu
ensure qb-input
ensure progressbarqb-menu, qb-input and progressbar are not part of Qbox. Ensure their shims only if you run older scripts that need them (the console then shows Could not find dependency qb-menu or No such export ShowInput).
4. Notifications (two edits in qbx_core)
qbx_core sends every notification to ox_lib. To have lumo-ui draw them:
qbx_core/client/functions.lua, in function Notify(...), just before the lib.notify({ line:
lua
if GetResourceState('lumo-ui') == 'started' then
local message = (title and description) and { text = description, caption = title } or description or title
return exports['lumo-ui']:Notify(message, notifyType == 'inform' and 'info' or notifyType, duration, notifyIcon)
end
lib.notify({qbx_core/server/functions.lua, in function Notify(source, ...), just before the TriggerClientEvent('ox_lib:notify', source, { line:
lua
if GetResourceState('lumo-ui') == 'started' then
local message = (title and description) and { text = description, caption = title } or description or title
return TriggerClientEvent('lumo-ui:client:notify', source, message, notifyType == 'inform' and 'info' or notifyType, duration)
end
TriggerClientEvent('ox_lib:notify', source, {Without these edits nothing breaks: ox_lib keeps drawing Qbox notifications. Re-apply them after updating qbx_core.
5. Radial menu: pick one
- Keep qbx_radialmenu: set
LumoUiConfig.Radial.Enabled = false. - Use Lumo's radial: move
qbx_radialmenuto[disabled]and copy its menu items intoLumoUiConfig.Radial.Items/JobItems(see the QBCore step 4 for the fields). Items that other scripts add withlib.addRadialItemstill go to ox_lib's own radial menu, not Lumo's.
6. Affected resources
| Resource | What to do |
|---|---|
QBCore.Functions.Progressbar (Qbox bridge) | Nothing. Qbox draws it with ox_lib's progress bar. |
| qbx_* resources (garages, police, ambulance, …) | Nothing. They keep using ox_lib and ox_target. |
| qbx_seatbelt, ox_fuel | Nothing. The HUD reads the seatbelt events and ox_fuel's fuel state bag. |
| Stress | Nothing. Read from metadata.stress, as on QBCore. |
Scripts using lib.progressBar, lib.registerContext, lib.inputDialog, lib.showTextUI | ox_lib keeps drawing those. Lumo UI does not replace ox_lib. |
ESX Legacy
ESX has no target eye, no radial and no HUD of its own, so Lumo UI adds those, and the ESX shims make ESX's own notifications, progress bar and key prompts use the Lumo look.
1. Move these folders from [core] to [disabled]
Old resource (in [core]) | Replaced by | Shim to ensure |
|---|---|---|
esx_notify | lumo-ui notifications | esx_notify |
esx_progressbar | lumo-ui progress bar | esx_progressbar |
esx_textui | lumo-ui key prompts | esx_textui |
any HUD (esx_hud, …) | lumo-ui HUD | — |
Keep these ESX resources running, Lumo UI does not replace them:
esx_menu_default,esx_menu_dialog,esx_menu_list(ESX.UI.Menu): the job, shop and boss menus of many ESX scripts use them.esx_context(ESX.OpenContext).
2. Target eye: pick one
- No target script yet: use Lumo's eye. Ensure the
qb-targetshim too, so scripts with a "qtarget" or "qb-target" option work with it. - You already run ox_target: keep it, set
LumoUiConfig.Target.Enabled = falseinlumo-ui/config.lua, and delete[compat]/qb-target(ox_target already answersexports.qtarget:*).
3. server.cfg
ESX's recipe ensures the whole [core] folder, so the order matters: Lumo UI and its shims go right after es_extended, before [core].
cfg
ensure oxmysql
ensure ox_lib # if you use it
ensure es_extended
ensure lumo-ui
ensure lumo-interact
ensure lumo-chat-theme # after chat
ensure esx_notify
ensure esx_progressbar
ensure esx_textui
ensure qb-target # only with Lumo's target eye (step 2)
ensure [core]
ensure [standalone]
ensure [esx_addons]No code edits are needed on ESX: ESX.ShowNotification, ESX.Progressbar, ESX.TextUI and ESX.HideUI look for these resource names and find the shims.
4. Radial items
ESX has no radial menu, so it starts with the product items (Emotes, Clothing) and the seated vehicle menu. Add your own in LumoUiConfig.Radial.Items and per job in LumoUiConfig.Radial.JobItems:
lua
LumoUiConfig.Radial.Items = {
-- type 'command' runs a chat command, 'client' / 'server' trigger an event
{ id = 'emotes', title = 'Emotes', icon = 'face-smile', type = 'command', event = 'emotes', shouldClose = true },
}
LumoUiConfig.Radial.JobItems = {
police = {
{ id = 'mdt', title = 'MDT', icon = 'tablet', type = 'client', event = 'yourmdt:client:open', shouldClose = true },
},
}Replace the commands and events with the ones your scripts already have.
5. Affected resources
| Resource | What to do |
|---|---|
| esx_status + esx_basicneeds | Needed for the hunger and thirst bars. Without them those bars stay full. |
ESX.UI.Menu / ESX.OpenContext menus | Nothing. ESX keeps drawing them (step 1). |
| esx_ambulancejob, cloakrooms | Nothing for Lumo UI. (If you use Lumo Clothing, it stands in for esx_skin.) |
Scripts with a target option ('qtarget', 'qb-target', 'ox_target') | Set the option to the target you chose in step 2. |
| Stress | Saved in the player's ESX metadata (stress). hud:server:GainStress / RelieveStress work. |
| Fuel | Found automatically (LegacyFuel, ox_fuel, …). |
Standalone
cfg
ensure oxmysql
ensure lumo-ui
ensure lumo-interact
ensure lumo-chat-theme # after chatOnly add shims for resources your scripts call by name. The HUD shows health, armour, voice, vehicle and minimap; status bars you feed yourself with exports['lumo-ui']:SetStatus('hunger', 80). Notifications: exports['lumo-ui']:Notify(text, type, duration) or the lumo-ui:client:notify event. See API.
After installing
- Restart the whole server once (not just the resource), so the shims and lumo-ui start in the right order.
- In game: press F1 for the radial, hold Left Alt for the target eye, type /ui for settings. Console line on start:
[lumo-ui] ready — framework: qb | qbx | esx | standalone. - Later, to restart only the UI, admins run /uirestart: it restarts the shims first, then lumo-ui.
- Keys are FiveM key bindings: players change them in Settings → Key Bindings → FiveM. Changing
Key/OpenKeyinconfig.luaonly changes the default for players who never pressed it.
Troubleshooting
| You see | Cause | Fix |
|---|---|---|
| Chat still has the default look | lumo-chat-theme not ensured, or another chat theme runs | Ensure chat, then lumo-chat-theme. If another chat theme runs (for example chat-theme-gtao from [cfx-default]), move it to [disabled] so the two styles do not mix. In F8, restart lumo-chat-theme reloads the style. |
Could not find dependency qb-target (or qb-menu, qb-input, progressbar) for a resource | The shim is not ensured | Ensure that shim after lumo-ui. |
No such export AddBoxZone in resource qb-target | The shim started before lumo-ui, or Target.Enabled = false | Ensure lumo-ui first and restart the server; with the eye off, use ox_target and delete the qb-target shim. |
| Two target eyes on Left Alt | ox_target and Lumo's eye both run | Set LumoUiConfig.Target.Enabled = false, or remove ox_target (not on Qbox). |
| Two HUDs on screen, or the HUD flickers | qb-hud / qbx_hud / ps-hud / esx_hud still runs | Move the old HUD to [disabled]. |
| Notifications still look old | Framework routing not set | QBCore: the qb-core edit. Qbox: the qbx_core edits. ESX: the esx_notify shim, with [core]/esx_notify moved out. Scripts that call lib.notify directly stay on ox_lib. |
ESX progress bar or [E] prompt still looks old | [core]/esx_progressbar or [core]/esx_textui still in resources/ | Move them to [disabled] and ensure the shims. |
| The old resource starts instead of the shim | Both folders are in resources/ | Move the original out of resources/ entirely. |
| Hunger and thirst stay full (ESX) | esx_status / esx_basicneeds not running | Install them, or feed the bars with SetStatus. |
| Fuel always full, or wrong | Fuel script not found | Set LumoUiConfig.Hud.Fuel to your fuel resource's name. |
| Radial does not open on F1 | F1 is bound by another script, or Radial.Enabled = false | Rebind it in Key Bindings → FiveM, or change LumoUiConfig.Radial.Key. |
/ui has no Admin tab | No permission | add_ace group.admin lumo.ui.admin allow, or a group from AdminPermissions. |
| Item pictures missing in menus | Inventory images not found | Set LumoUiConfig.Menu.ImagePath to your inventory's image folder, e.g. nui://ox_inventory/web/images/. |
Players' /ui layout reset after moving from the Lumo HUD | Settings are saved per resource name | Expected once; players set it again. |
Still stuck? Open a ticket with your framework, the F8 console error and the resource that called lumo-ui.
Going back
Stop lumo-ui, lumo-interact and the shims, move the original resources back from [disabled], undo the notify edits and restore your server.cfg. Nothing in the database is changed, except the stress value Lumo UI shares with qb-hud.