Documentation Index
Fetch the complete documentation index at: https://docs.9am.dev/llms.txt
Use this file to discover all available pages before exploring further.
9AM TextUI overview
9AM TextUI is a free animated Text UI replacement for FiveM that supports both 3D world-space and screen-space rendering with smooth morphing animations. It automatically overrides ox_lib’s Text UI so all existing scripts use it without code changes.
Public features
- 3D world prompts rendered at world coordinates with camera projection tracking
- Classic screen-anchored overlay mode
- Drop-in
ox_lib override for lib.showTextUI / lib.hideTextUI
- Sphere, box, and poly zone types via
ox_lib
- Distance-based animation that expands when near and collapses into a dot when far
- Configurable accent color
- Free and open source
Dependencies
Compatibility and editions
| Type | Details |
|---|
| Compatibility | Standalone |
| Price | Free |
Config
-- config.lua
Config.PrimaryColor = '#f7e472'
Config.Zones = {
{
id = 'management-menu',
text = 'Open Management',
key = 'E',
coords = vec3(-34.9118, -1102.1649, 26.4224),
displayDist = 10.0,
nearDist = 2.0,
offset = vec3(0.0, 0.0, -0.6),
},
}
Zone options
| Option | Type | Default | Description |
|---|
id | string | — | Unique identifier (required) |
text | string | — | Prompt label |
key | string | "" | Key hint in the badge (e.g. 'E') |
coords | vec3 | — | World position |
displayDist | number | 10.0 | Distance at which the prompt is visible |
nearDist | number | 2.0 | Distance at which the prompt expands |
offset | vec3 | (0, 0, 1) | Offset from coords for display anchor |
type | string | 'sphere' | Zone type: sphere, box, or poly |
radius | number | displayDist | Zone radius (sphere only) |
size | vec3 | — | Zone dimensions (box only) |
rotation | number | — | Zone rotation (box only) |
points | table | — | Zone vertices (poly only) |
thickness | number | — | Zone height (poly only) |
debug | boolean | false | Draw debug zone outline |
Exports
3D World TextUI
-- Create
exports['9am-textui']:createTextUI('shop-door', {
text = 'Open Shop',
key = 'E',
coords = vec3(250.0, -850.0, 29.5),
displayDist = 10.0,
nearDist = 2.0,
})
-- Update (partial, only changed fields)
exports['9am-textui']:updateTextUI('shop-door', { text = 'Closed' })
-- Remove
exports['9am-textui']:removeTextUI('shop-door')
Screen Overlay TextUI
-- Show (key is parsed from [X] prefix)
exports['9am-textui']:showOverlayTextUI('[E] Open Menu')
-- Show at world coords
exports['9am-textui']:showOverlayTextUI('[E] Open Menu', {
coords = vec3(100.0, 200.0, 30.0),
})
-- Hide
exports['9am-textui']:hideOverlayTextUI()
-- Check state
local isOpen = exports['9am-textui']:isOverlayTextUIOpen()
ox_lib override
The included override.lua replaces lib.showTextUI / lib.hideTextUI globally. Two ways to set it up:
Option A — Add directly to ox_lib (recommended, applies to all resources automatically):
Copy override.lua into ox_lib/imports/ (or any loaded path), then add it to ox_lib’s fxmanifest.lua:
files { '@9am-textui/override.lua' }
client_scripts { '@9am-textui/override.lua' }
Option B — Per resource:
Add to the target resource’s fxmanifest.lua:
files { '@9am-textui/override.lua' }
client_scripts { '@9am-textui/override.lua' }
After either setup, these calls route through 9am-textui automatically:
lib.showTextUI('[E] Interact')
lib.hideTextUI()
lib.isTextUIOpen()
Advanced zone types
Box
exports['9am-textui']:createTextUI('garage', {
text = 'Enter Garage',
key = 'E',
type = 'box',
coords = vec3(200.0, -800.0, 30.0),
size = vec3(10.0, 6.0, 4.0),
rotation = 45.0,
displayDist = 15.0,
})
Poly
exports['9am-textui']:createTextUI('park', {
text = 'Rest Area',
key = 'G',
type = 'poly',
points = {
vec3(100.0, 200.0, 30.0),
vec3(110.0, 200.0, 30.0),
vec3(110.0, 210.0, 30.0),
vec3(100.0, 210.0, 30.0),
},
thickness = 4.0,
displayDist = 20.0,
})
Poly zones don’t require coords — defaults to the centroid of the points.
Example
CreateThread(function()
exports['9am-textui']:createTextUI('atm_legion', {
text = 'Use ATM',
key = 'E',
coords = vec3(149.0, -1040.0, 29.4),
displayDist = 5.0,
nearDist = 1.5,
offset = vec3(0.0, 0.0, 0.5),
})
end)
-- Dynamic update
RegisterNetEvent('bank:client:toggleATM', function(enabled)
if enabled then
exports['9am-textui']:updateTextUI('atm_legion', { text = 'Use ATM', key = 'E' })
else
exports['9am-textui']:updateTextUI('atm_legion', { text = 'Out of Service', key = '' })
end
end)
-- Cleanup
AddEventHandler('onResourceStop', function(res)
if res == GetCurrentResourceName() then
exports['9am-textui']:removeTextUI('atm_legion')
end
end)
Best for
Choose this script if you want:
- A visually polished Text UI with smooth animations at no cost
- 3D world-space prompts that track camera projection
- A seamless
ox_lib Text UI replacement without changing existing code
Download link
Open TextUI in the store