Building & internals
Layout
fxmanifest.lua
shared/lib/*.lua Hud global, validators, notify/prompt/progress normalisation
shared/config.lua Config.*
shared/locales.lua
bridge/framework/client/ 0_common 1_qbx 2_qb 3_esx 9_standalone
bridge/voice/client/ 0_common 1_pma 2_saltychat 3_yaca 9_none
client/data/weapons.lua weapon labels (GTA has no label native for weapon hashes)
client/core/ state, config, NUI bridge, theme, visibility, per-frame tasks
client/modules/ player, vehicle, weapon, voice, location, minimap, seatbelt, framework,
notify, prompt, progress, hotbar, world, helicam (np_helicam compat), demo
server/ player count, server notifications
web/ NUI (Vite + React 18 + TS strict + zustand)
design/ Nimbus UI: tokens, components, previewsNUI
sh
cd web
npm install
npm run dev # http://localhost:5174, mock data + dev panel
npm run typecheck
npm run build # → web/distOutside FiveM, src/dev feeds demo data through the same dispatchNui path Lua uses. It paints a city scene and a fake native radar under the minimap frame, and shows a floating dev panel with scenes, themes, every notification variant, the Y/N keys, prompt and progress, and state toggles.
| URL parameter | Effect |
|---|---|
?scene=vehicle|foot | Scene |
&brand=%233d74ff&strength=accent|tiles|glass | Theme |
&server=Blue%20Line | Server name |
&shot=1 | Hides the panel and freezes demo data (for screenshots) |
&live=0 | No speed / heading wobble |
Screenshots
sh
npx vite preview --port 4317
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless=new --disable-gpu --hide-scrollbars \
--virtual-time-budget=6000 --window-size=1920,1080 --screenshot=screenshots/vehicle.png \
'http://localhost:4317/?shot=1&scene=vehicle'Then run npm run sync:images in this docs repo.
NUI implementation notes
These are the decisions the web side made where the NUI contract leaves room.
- Scaling.
.nb-hudgetszoom = innerHeight / 1080 × config.scale. Zones anchor to the screen edges, so ultrawide works. - Minimap rect.
config.minimap {x,y,w,h}is in 1080p-reference pixels from the top-left of the viewport, scaled byinnerHeight/1080only (not byconfig.scale). The frame is a 5 px glass ring drawn inside the rect, with a transparent centre that the native minimap fills. - Heading. A compass bearing (0 = N, 90 = E, clockwise). GTA's
GetEntityHeadingruns counter-clockwise, so Lua sends(360 - heading) % 360. - Low states. A tile gets
.is-lowwhen its value is ≤lowThreshold(health, hunger, thirst, stamina, oxygen, fuel, engine). Stress is inverted, and armour never alarms. A weapon is low when its clip is ≤ threshold % ofclipSize. - Seatbelt. The belt tile is red, with a ring and the "Belt off!" label, only when
showBelt && !seatbelt. - Streamer mode. The server chip shows "Server" plus the server name, and the id is hidden.
- Toasts.
announcegoes top-centre, one at a time. Every other variant goes in the top-right stack, capped atmaxToasts. A click on an action, or itsnotify:key, postsnotifyActionand dismisses the toast. - Sound.
sound: trueplays a WebAudio blip in the NUI. Lua doesn't also play a frontend sound. - Progress. One bar at a time. Replacing a bar or cancelling it posts
progressDone {cancelled:true}, so Lua's blockingProgress()always resolves. - Theme.
hud:config.themesets the server default. A laterthememessage overrides it until the nexthud:configthat carriestheme. - Hotbar. Shown only when
components.hotbaris on andvisible ~= false. Lua owns auto-hiding.
Capability notes
| Feature | Source | Notes |
|---|---|---|
| Status, vehicle, weapon, voice, location | native + NUI | Polled at the slowest practical interval. The vehicle and weapon loops only run while they're needed |
| Minimap placement | native | SetMinimapComponentPosition plus a big-map reload. The conversion assumes a centred 16:9 layout on ultrawide and a (1 - safezone) / 2 margin. Override it with Config.Minimap.native |
| Rounded minimap corners | asset-dependent | The native minimap is clipped by the radarmasksm texture. A matching custom mask texture is a follow-up |
| Health/armour bars under the minimap | native | Hidden through the minimap scaleform (SETUP_HEALTH_ARMOUR 3), re-applied every second |
| Seatbelt ejection | native, approximate | Detected from a speed drop between two 100 ms vehicle ticks |
| Weapon names | data | Common weapons are in client/data/weapons.lua. Others show their group name |
| Player count | server | GlobalState set by np_hud's server script |