Frameworks
Getting started with ox_lib
A practical ox_lib guide for FiveM developers: installing and importing it, cache, callbacks, notifications, progress bars, context menus, input dialogs, text UI, points and zones, lib.addCommand with ACE restrictions, keybinds and locale convars — with copy-paste examples.
Overview
ox_lib by Overextended is the standard utility library of modern FiveM servers: callbacks, notifications, progress bars, menus, input dialogs, zones, commands and a cache of common values, usable from any framework. Learning it saves you from writing — and debugging — the same helpers in every script.
01Installing and importing
- Download the latest release build of ox_lib from Overextended’s GitHub releases (not the source code zip — the release contains the built UI).
- Place it in
resourcesand addensure ox_libto server.cfg above your frameworks and scripts. - In each resource that uses it, import it in the fxmanifest.
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
shared_script '@ox_lib/init.lua'
client_script 'client.lua'
server_script 'server.lua'
dependency 'ox_lib'setr ox:locale en
setr ox:primaryColor blue
setr ox:primaryShade 8cache
ox_lib keeps frequently used values up to date so you do not call natives every frame: cache.ped, cache.playerId, cache.serverId, cache.vehicle (or false), cache.seat, cache.weapon (or false), plus cache.resource. React to changes with lib.onCache.
lib.onCache('vehicle', function(vehicle)
if vehicle then
print('entered', GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)))
end
end)Callbacks
lib.callback.register('bank:getBalance', function(source)
local player = exports.qbx_core:GetPlayer(source) -- or your framework
return player and player.PlayerData.money.bank or 0
end)local balance = lib.callback.await('bank:getBalance', false)
lib.notify({ title = 'Bank', description = ('Balance: $%d'):format(balance), type = 'inform' })The second argument of lib.callback.await is a client-side rate limit in milliseconds (false for none). Callbacks are requests like events — validate inside them. More in callbacks explained.
Notifications, progress and dialogs
lib.notify({ title = 'Garage', description = 'Vehicle stored', type = 'success' })
if lib.progressBar({
duration = 5000,
label = 'Repairing engine',
useWhileDead = false,
canCancel = true,
disable = { car = true, move = true, combat = true },
anim = { dict = 'mini@repair', clip = 'fixing_a_player' },
}) then
print('finished')
else
print('cancelled')
end
local input = lib.inputDialog('Transfer', {
{ type = 'number', label = 'Player ID', required = true },
{ type = 'number', label = 'Amount', required = true, min = 1 },
})
if input then
TriggerServerEvent('bank:transfer', input[1], input[2])
end| Function | Shows |
|---|---|
lib.notify | Toast notification (success, error, warning, inform) |
lib.progressBar / lib.progressCircle | Timed action; returns true if completed |
lib.inputDialog | Form; returns an array of values or nil |
lib.alertDialog | Confirm dialog; returns 'confirm' or 'cancel' |
lib.showTextUI / lib.hideTextUI | Persistent hint such as “[E] Open” |
lib.registerContext / lib.showContext | Context menus |
lib.registerMenu / lib.showMenu | Keyboard-driven list menus |
Context menus
lib.registerContext({
id = 'garage_menu',
title = 'Garage',
options = {
{ title = 'Take out vehicle', icon = 'car', onSelect = function() TriggerServerEvent('garage:takeOut') end },
{ title = 'Store vehicle', icon = 'warehouse', serverEvent = 'garage:store' },
{ title = 'Locked option', disabled = true },
},
})
lib.showContext('garage_menu')Points and zones
local point = lib.points.new({
coords = vec3(215.8, -810.1, 30.7),
distance = 3.0,
onEnter = function() lib.showTextUI('[E] Open garage') end,
onExit = function() lib.hideTextUI() end,
nearby = function()
if IsControlJustReleased(0, 38) then lib.showContext('garage_menu') end
end,
})
lib.zones.box({
coords = vec3(441.0, -982.0, 30.7),
size = vec3(6.0, 6.0, 3.0),
rotation = 0.0,
debug = false,
onEnter = function() lib.notify({ description = 'Entered Mission Row' }) end,
})nearby only runs while the player is inside the distance, so the idle cost stays near zero. Zones in depth: zones with ox_lib.
Commands and keybinds
lib.addCommand('givecash', {
help = 'Give cash to a player',
params = {
{ name = 'target', type = 'playerId', help = 'Server ID' },
{ name = 'amount', type = 'number', help = 'Amount' },
},
restricted = 'group.admin',
}, function(source, args)
-- args.target and args.amount are already parsed
end)restricted accepts an ACE principal such as group.admin (or a list); ox_lib adds the ACE for the command. On the client, lib.addKeybind wraps key mapping so players can rebind keys in the settings — see commands and key mapping.
Frequently asked questions
How do I use ox_lib in my script?
Add shared_script '@ox_lib/init.lua' and lua54 'yes' to the fxmanifest and start ox_lib before your resource.
Why is lib nil in my script?
The import is missing from the fxmanifest, ox_lib is not started before your resource, or you downloaded the source instead of a release build.
Is ox_lib framework-specific?
No. It works with ESX, QBCore, Qbox, ox_core and standalone scripts.
How do I change the ox_lib language?
Set setr ox:locale <code> in server.cfg, for example setr ox:locale de.
What does the second argument of lib.callback.await do?
It is a client-side rate limit (delay in ms) between calls; pass false for none.
Need this built, not just explained?
Ten years of FiveM work, from Lua to NUI
Custom resources, React NUI, ESX / QBCore / Qbox integration, OneSync performance audits and security reviews — plus the websites and SEO around your server brand.
Related guides
- FrameworksCallbacks: asking the server a question and getting an answerA callback registers a named handler on one side and lets the other side call it and receive its return value. With ox_lib use lib.callback.register on the server and lib.callback.await on the client (it also works server → client). ESX uses ESX.RegisterServerCallback / ESX.TriggerServerCallback, QBCore QBCore.Functions.CreateCallback / QBCore.Functions.TriggerCallback. Validate inside callbacks exactly like events.
- FrameworksCreating zones in FiveM with ox_lib (and PolyZone)With ox_lib, create zones with lib.zones.box, lib.zones.sphere or lib.zones.poly and handle onEnter, onExit and inside. Use the restricted /zone poly|box|sphere command to draw zones in game; ox_lib saves them to created_zones.lua. PolyZone is the older library many QBCore resources still use. Zones run on the client — confirm anything important on the server.
- EngineeringCommands and rebindable keys in FiveMRegister a command with RegisterCommand(name, handler, restricted). Setting restricted to true on the server requires the ACE command.name. Bind a client command to a rebindable key with RegisterKeyMapping(command, description, 'keyboard', 'F5'), which adds it to the game’s Key Bindings settings. Use +name/-name commands for keys that act while held.
- EngineeringExports: calling functions in another FiveM resourceDefine an export with exports('name', function(...) end) in Lua (or list the function under export/server_export in the manifest), then call it from another resource with exports.resource:name(...) or exports['resource-name']:name(...). Exports work on the same side only — client exports from client scripts, server exports from server scripts — and return values directly, unlike events.