How to Set Up ox_lib in FiveM for QBCore & ESX (2026)
Step-by-step guide to installing and configuring ox_lib on your FiveM server. Covers context menus, notifications, progress bars, input dialogs, zones, and integration with both QBCore and ESX.
What Is ox_lib and Why Every Server Needs It
ox_lib is an open-source utility library maintained by the Overextended team. It provides a standardized set of UI components, math helpers, and shared functions that work across ESX, QBCore, and QBOX. Instead of every script implementing its own notification system, progress bar, and input dialog — ox_lib gives you a single, performant implementation that every resource can share.
In 2026, ox_lib is a de facto dependency for most modern FiveM scripts. If you are starting a new server or upgrading an existing one, installing it correctly from the start saves hours of compatibility issues later.
Step 1: Download and Install
Requirements
- A running FiveM server with txAdmin
- Either QBCore, ESX, or QBOX as your framework
oxmysql(the Overextended MySQL resource) — required for some ox_lib features
Installation
- Download the latest release from the ox_lib GitHub releases page. Always use the release build, not the source code.
- Extract the
ox_libfolder into your server'sresourcesdirectory:
# Your server structure should look like:
resources/
├── [framework]/
├── ox_lib/
│ ├── fxmanifest.lua
│ ├── resource/
│ ├── imports/
│ └── ...
- Add it to your
server.cfgbefore any resource that depends on it:
ensure oxmysql
ensure ox_lib
ensure qb-core # or es_extended
ensure ox_target # if using ox_targetImportant: ox_lib must be ensured before any resource that uses it. If you see errors like SCRIPT ERROR: @ox_lib/init.lua on startup, the load order is wrong.
Step 2: Configure the Locale
ox_lib supports multiple languages. The default is English. To change it, edit ox_lib/resource/config.lua:
return {
locale = 'en039;, -- Change to 039;de039;, 039;es039;, 039;fr039;, etc.
}
Locale files are stored in ox_lib/locales/. You can add your own by copying en.json and translating the strings.
Step 3: Using Context Menus
Context menus replace the clunky old menu systems. They support icons, descriptions, progress indicators, and nested submenus.
Basic Context Menu
lib.registerContext({
id = 'my_garage_menu039;,
title = 'Personal Garage039;,
options = {
{
title = 'Spawn Vehicle039;,
description = 'Spawn your personal vehicle039;,
icon = 'car039;,
onSelect = function()
TriggerServerEvent('garage:spawn039;)
end,
},
{
title = 'Store Vehicle039;,
description = 'Store your current vehicle039;,
icon = 'warehouse039;,
onSelect = function()
TriggerServerEvent('garage:store039;)
end,
},
{
title = 'Vehicle List039;,
description = 'Browse all your vehicles039;,
icon = 'list039;,
menu = 'vehicle_list_submenu039;, -- Opens a submenu
},
},
})
lib.showContext('my_garage_menu039;)
Context Menu with Server Data
-- Client: request vehicles from server, then build menu dynamically
lib.callback('garage:getVehicles039;, false, function(vehicles)
local options = {}
for _, v in ipairs(vehicles) do
options[#options + 1] = {
title = v.label,
description = string.format('Plate: %s | Fuel: %d%%039;, v.plate, v.fuel),
icon = 'car039;,
metadata = {
{ label = 'Model039;, value = v.label },
{ label = 'Plate039;, value = v.plate },
},
onSelect = function()
TriggerServerEvent('garage:spawnVehicle039;, v.plate)
end,
}
end
lib.registerContext({
id = 'vehicle_list_submenu039;,
title = 'Your Vehicles039;,
menu = 'my_garage_menu039;, -- Back button returns here
options = options,
})
lib.showContext('vehicle_list_submenu039;)
end)Step 4: Progress Bars and Circles
ox_lib provides both linear progress bars and circular progress indicators. These are used for actions like crafting, repairing, or fishing.
Progress Bar
if lib.progressBar({
duration = 5000,
label = 'Repairing Vehicle039;,
useWhileDead = false,
canCancel = true,
disable = {
car = true,
move = true,
combat = true,
},
anim = {
dict = 'mini@repair039;,
clip = 'fixing_a_ped039;,
},
}) then
-- Completed successfully
TriggerServerEvent('mechanic:repairComplete039;)
else
-- Cancelled by player
lib.notify({ description = 'Repair cancelled039;, type = 039;error039; })
endProgress Circle
if lib.progressCircle({
duration = 3000,
label = 'Searching...039;,
position = 'bottom039;,
useWhileDead = false,
canCancel = false,
disable = {
move = true,
},
}) then
-- Success
endPerformance note: ox_lib progress bars use minimal NUI. The animation is CSS-based with no JavaScript polling, keeping client ms near zero during the animation.
Step 5: Notifications
Replace your framework's native notifications with ox_lib for a consistent look across all resources:
-- Simple notification
lib.notify({
title = 'Job Update039;,
description = 'You have been promoted to Sergeant039;,
type = 'success039;, -- 039;success039;, 039;error039;, 039;warning039;, 039;info039;
duration = 5000,
position = 'top039;, -- 039;top039;, 039;top-right039;, 039;bottom039;, etc.
})
-- Notification with icon
lib.notify({
title = 'New Item039;,
description = 'You received 1x Radio039;,
type = 'info039;,
icon = 'radio039;,
iconColor = '#3b82f6039;,
})
Replacing QBCore Notifications
To make all QBCore scripts use ox_lib notifications without editing every resource, override the function in your QBCore config:
-- In qb-core/client/functions.lua, find QBCore.Functions.Notify and replace:
function QBCore.Functions.Notify(text, texttype, length)
lib.notify({
description = text,
type = texttype or 'info039;,
duration = length or 5000,
})
endStep 6: Input Dialogs
For collecting player input — names, numbers, selections — ox_lib provides a clean dialog system:
local input = lib.inputDialog('Create Job Posting039;, {
{ type = 'input039;, label = 039;Job Title039;, required = true, placeholder = 039;e.g. Mechanic039; },
{ type = 'number039;, label = 039;Salary039;, required = true, min = 100, max = 50000 },
{ type = 'select039;, label = 039;Type039;, required = true,
options = {
{ value = 'whitelisted039;, label = 039;Whitelisted039; },
{ value = 'public039;, label = 039;Public039; },
}
},
{ type = 'textarea039;, label = 039;Description039;, required = false, placeholder = 039;Job description...039; },
})
if input then
local title = input[1]
local salary = input[2]
local jobType = input[3]
local desc = input[4]
TriggerServerEvent('jobs:create039;, title, salary, jobType, desc)
endStep 7: Zones (PolyZone Replacement)
ox_lib includes a built-in zone system that replaces PolyZone. It is more performant and simpler to configure:
-- Sphere zone
local zone = lib.zones.sphere({
coords = vec3(215.0, -810.0, 30.0),
radius = 5.0,
debug = false,
onEnter = function()
lib.notify({ description = 'Entered the shop zone039;, type = 039;info039; })
end,
onExit = function()
lib.notify({ description = 'Left the shop zone039;, type = 039;info039; })
end,
inside = function()
-- Runs every frame while inside - use sparingly
if IsControlJustPressed(0, 38) then -- E key
lib.showContext('shop_menu039;)
end
end,
})
-- Remove zone when no longer needed
zone:remove()
Box Zone
lib.zones.box({
coords = vec3(440.0, -980.0, 30.7),
size = vec3(4.0, 4.0, 3.0),
rotation = 45,
debug = false,
onEnter = function()
-- Show interaction prompt
end,
})
Tip: Set debug = true during development to see the zone boundaries rendered in-game. Disable it in production.
Integrating ox_lib with Alone Scripts
All scripts from Alone Scripts auto-detect ox_lib when present and use it for menus, notifications, and progress bars. Our Jobs Creator uses ox_lib zones for marker areas and ox_lib context menus for the employee management interface. No manual bridging needed — just ensure ox_lib before our resources.
If you are running both QBCore native menus and ox_lib, Jobs Creator will prefer ox_lib automatically. The Dynamic Fishing system uses ox_lib progress circles for the fishing minigame tension bar.
Ready to Transform Your Server?
FiveM Job Creator eliminates every problem discussed in this article. 0.00ms resmon. No-code configuration. ESX & QBCore native.
Get Job Creator — €29.99