Common concepts
The np_* resources share a set of patterns. Each resource's Bridges page has the details for that resource.
Bridges and auto-detection
Resources never call a framework or voice resource directly. They go through a bridge: a small Lua table with a fixed contract (for example Phone.Framework.getMoney(src, 'bank') or Hud.Voice.get()), plus one implementation file per supported resource.
bridge/framework/client/1_qbx.lua
bridge/framework/client/2_qb.lua
bridge/framework/client/3_esx.lua
bridge/voice/…- Every bridge file starts with
Bridge.shouldLoad(kind, name, resource)and returns early unless its resource is started and selected. Config.Framework/Config.Voiceselect a bridge.'auto'takes the first one that is started. The files are numbered so thatautoprefers qbx over qb (qbx also providesqb-core) and pma-voice over the other voice resources.- Optional exports are called through
pcall, so a missing or broken dependency degrades a feature instead of throwing errors. - Detection runs once at resource start, so start optional dependencies first in
server.cfg. - np_mdt is the exception to the naming above: it also bridges target, UI and database, prefers ESX, and is overridden with
Config.Bridge. See MDT bridges.
| Kind | Supported | Fallback |
|---|---|---|
| Framework | qbx_core, qb-core, es_extended | np_hud: standalone · np_phone: required · np_menu: standalone · np_helicam: standalone (ACE roles) · np_mdt: standalone |
| Voice | pma-voice, saltychat, yaca-voice | none: talking indicator only / UI-only calls |
| Inventory | ox_inventory, then the framework inventory | – |
Configuration
shared/config.luaholds the core settings. Bigger resources split areas intoshared/config/<area>.lua(for exampleConfig.Comms,Config.City).- Config files are shared (loaded on client and server), so anything in them is visible to players.
Secrets
Tokens, webhooks and peppers never go in a config file. Read them from server convars in server.cfg, using set and not setr, so they aren't replicated to clients:
cfg
set np_phone:fivemanage_token "your-api-key"NUI
- Each resource has a
web/folder (Vite + React + TypeScript strict) that builds toweb/dist. - Lua → NUI:
SendNUIMessage. NUI → Lua:fetch('https://<resource>/<name>')NUI callbacks. - Every resource documents its message contract (see np_hud NUI contract, np_phone architecture and np_menu NUI contract).
npm run devruns the NUI in a browser with mock data, so you can work on the UI without a FiveM server.
Performance
- Nothing polls while it isn't needed. Loops start when there is something to do (in a vehicle, while armed, while the phone is open).
- The idle resmon target is 0.00 ms.
Security
- The server is authoritative. Money, items, vehicles and ownership are validated on the server, and client values are never trusted.
- NUI → server calls are rate-limited and type-checked.
- Server-local events (
AddEventHandler) fire only after validation. Never listen to the raw net events from other resources.