Build a teleport menu, step by step
By the end of this lesson you will type /tpmenu, click a place name, and watch your character arrive there with a smooth fade. The server approves destinations for this resource and can enforce permissions or write an audit entry. This is not an anti-teleport system: an exploited client can still call client natives directly.
Build it
Make the resource folder
Inside your server's resources folder, create this folder:
resources/qu_teleport_menu
Create the files
Create this exact file layout:
resources/qu_teleport_menu/
fxmanifest.lua
server.lua
client.lua
Write fxmanifest.lua
Open fxmanifest.lua and paste this:
fx_version 'cerulean'
game 'gta5'
shared_script '@ox_lib/init.lua'
client_script 'client.lua'
server_script 'server.lua'
dependencies {
'ox_lib'
}
Two things to know about this manifest. There is no lua54 'yes' line: as of June 2025 that directive is deprecated and ignored, because Lua 5.4 is now the only Lua runtime. And ox_lib is a Community Ox library, not a built-in Cfx.re resource. You install it yourself and it must be running before this resource, which is what the dependencies block enforces.
Write the lesson code
Open server.lua and paste this:
local allowed = { legion = true, airport = true }
RegisterNetEvent('qu_teleport_menu:request', function(destination)
local src = source
if not allowed[destination] then
print('[qu_teleport_menu] rejected source ' .. src .. ' for ' .. tostring(destination))
return
end
print('[qu_teleport_menu] approved source ' .. src .. ' for ' .. destination)
TriggerClientEvent('qu_teleport_menu:approved', src, destination)
end)
Open client.lua and paste this:
local spots = {
legion = vec3(215.76, -810.12, 30.73),
airport = vec3(-1037.62, -2737.86, 20.17),
}
RegisterCommand('tpmenu', function()
lib.registerContext({
id = 'qu_teleport_menu_menu',
title = 'Teleport',
options = {
{ title = 'Legion Square', onSelect = function() TriggerServerEvent('qu_teleport_menu:request', 'legion') end },
{ title = 'Airport', onSelect = function() TriggerServerEvent('qu_teleport_menu:request', 'airport') end },
},
})
lib.showContext('qu_teleport_menu_menu')
end, false)
RegisterNetEvent('qu_teleport_menu:approved', function(destination)
local c = spots[destination]
if not c then return end
DoScreenFadeOut(500)
Wait(600)
SetEntityCoords(PlayerPedId(), c.x, c.y, c.z, false, false, false, false)
DoScreenFadeIn(500)
print('[qu_teleport_menu] moved to ' .. destination)
end)
Start and test it
Open server.cfg and add this line (after the line that ensures ox_lib):
ensure qu_teleport_menu
Save, then run this in the server console (txAdmin Live Console or the FXServer console). Because this resource has never started yet, use ensure, which starts it if it is stopped (restart only works once a resource is already running):
refresh
ensure qu_teleport_menu
After this first start, you can use restart qu_teleport_menu whenever you edit the code and want to reload it.
Join the server, then run this test in the chat box (press T):
/tpmenu
Choose Legion Square from the menu. Your screen fades out, you arrive at Legion, and the screen fades back in.
Keep reading the full lesson
Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.
- How it works
- A second shape: the /tp [number] command
- If something went wrong
- What you can do now
- Try it yourself
The remainder of Teleport menu with ox_lib is available to FiveM School members.