Skip to content

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, previews

NUI ​

sh
cd web
npm install
npm run dev        # http://localhost:5174, mock data + dev panel
npm run typecheck
npm run build      # → web/dist

Outside 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 parameterEffect
?scene=vehicle|footScene
&brand=%233d74ff&strength=accent|tiles|glassTheme
&server=Blue%20LineServer name
&shot=1Hides the panel and freezes demo data (for screenshots)
&live=0No 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-hud gets zoom = 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 by innerHeight/1080 only (not by config.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 GetEntityHeading runs counter-clockwise, so Lua sends (360 - heading) % 360.
  • Low states. A tile gets .is-low when 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 % of clipSize.
  • 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. announce goes top-centre, one at a time. Every other variant goes in the top-right stack, capped at maxToasts. A click on an action, or its notify:key, posts notifyAction and dismisses the toast.
  • Sound. sound: true plays 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 blocking Progress() always resolves.
  • Theme. hud:config.theme sets the server default. A later theme message overrides it until the next hud:config that carries theme.
  • Hotbar. Shown only when components.hotbar is on and visible ~= false. Lua owns auto-hiding.

Capability notes ​

FeatureSourceNotes
Status, vehicle, weapon, voice, locationnative + NUIPolled at the slowest practical interval. The vehicle and weapon loops only run while they're needed
Minimap placementnativeSetMinimapComponentPosition 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 cornersasset-dependentThe native minimap is clipped by the radarmasksm texture. A matching custom mask texture is a follow-up
Health/armour bars under the minimapnativeHidden through the minimap scaleform (SETUP_HEALTH_ARMOUR 3), re-applied every second
Seatbelt ejectionnative, approximateDetected from a speed drop between two 100 ms vehicle ticks
Weapon namesdataCommon weapons are in client/data/weapons.lua. Others show their group name
Player countserverGlobalState set by np_hud's server script

np_* FiveM resources