Description
A complete, minimal ESX job resource: it registers a custom job
(garbage) with three graded ranks and salaries, then exposes clock-in and
clock-out events so a player can take and drop the job at runtime. This is the
canonical starting point for any role-based gameplay on an ESX server — police,
EMS, mechanic, and delivery jobs are all variations on this skeleton.
Prompt Template
You are writing a FiveM server script for es_extended (stable, exports-based
getSharedObject). Create a single server-side Lua file that:
1. Registers a job named "[JOB_NAME]" with label "[JOB_LABEL]" and these
grades: [GRADES — list of {grade, name, label, salary}].
2. Inserts the job into ESX.Jobs directly (do NOT call ESX.RegisterJob — it does
not exist in stable es_extended).
3. Adds RegisterNetEvent handlers "[RESOURCE]:clockIn" (accepts a grade) and
"[RESOURCE]:clockOut" (sets the player to unemployed), each resolving the
xPlayer via ESX.GetPlayerFromId(source) and guarding against nil.
4. Registers the job inside onResourceStart, guarded with
GetCurrentResourceName() so it only runs for THIS resource.
Return only the Lua. No prose, no markdown fences.
Expected Output
See content/expected-outputs/jobs/01-basic-job-system.lua. It is
syntax-validated with luaparse (our build gate); it has not been run
against a live FiveM server, so treat it as a verified-syntax starting point,
not a drop-in guarantee.
-- 01-basic-job-system.lua
-- Server-side ESX job registration + clock-in/out for a basic "garbage" job.
-- Drop into a resource's server/ folder; requires es_extended.
local ESX = exports["es_extended"]:getSharedObject()
-- Job definition registered on resource start.
local JOB_NAME = "garbage"
local JOB_LABEL = "Garbage Collector"
local JOB_GRADES = {
{ grade = 0, name = "recruit", label = "Recruit", salary = 200 },
{ grade = 1, name = "driver", label = "Driver", salary = 350 },
{ grade = 2, name = "boss", label = "Boss", salary = 600 },
}
-- Register the job + its grades with ESX's in-memory job table.
local function registerJob()
local grades = {}
for _, g in ipairs(JOB_GRADES) do
grades[tostring(g.grade)] = {
job_name = JOB_NAME,
grade = g.grade,
name = g.name,
label = g.label,
salary = g.salary,
skin_male = "{}",
skin_female = "{}",
}
end
ESX.Jobs[JOB_NAME] = {
name = JOB_NAME,
label = JOB_LABEL,
grades = grades,
}
end
-- Clock a player into the job at the given grade (defaults to recruit).
RegisterNetEvent("basic-job:clockIn", function(grade)
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
if not xPlayer then return end
local targetGrade = tonumber(grade) or 0
xPlayer.setJob(JOB_NAME, targetGrade)
TriggerClientEvent("esx:showNotification", src, "You clocked in as " .. JOB_LABEL)
end)
-- Clock a player back out to unemployed.
RegisterNetEvent("basic-job:clockOut", function()
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
if not xPlayer then return end
xPlayer.setJob("unemployed", 0)
TriggerClientEvent("esx:showNotification", src, "You clocked out.")
end)
AddEventHandler("onResourceStart", function(resourceName)
if GetCurrentResourceName() == resourceName then
registerJob()
end
end)
Known Failure Modes
- Hallucinated
ESX.RegisterJob— not a real stable-ESX function. The prompt explicitly forbids it; if Claude still emits it, insert intoESX.Jobsdirectly or seed thejobs/job_gradesDB tables. - Wrong
getSharedObjectretrieval — exports vs. legacyTriggerEventcallback differs by ESX version. Pin the version in your prompt. - Unguarded
onResourceStart— without theGetCurrentResourceName()check the job re-registers on every resource start.
Integration Notes
- Place the file under your resource's
server/folder and list it as aserver_scriptinfxmanifest.lua. es_extendedmust start before this resource (set it as a dependency).- To persist the job across restarts, also insert it into the
jobsandjob_gradesdatabase tables — the in-memory registration here is lost on server restart.
Profit Potential
$300–$4000/mo on Tebex (expected ~$1100). [INFERRED] priced inside the $50-389 script band against the signal-scraper tebex_snapshot corpus (median seller $11.85K/mo, n=100), scaled for a hot job-systems niche at beginner difficulty — high unit volume on a low ticket.
Trend Signal
🔥 hot — custom FiveM job systems = niche-selection LAUNCH #1 (4.75).
Sales Angle
Position as the boilerplate every server owner clones on day one — graded ranks, salaries, and clock-in/out with zero bloat. Sell cheap as a funnel into your paid jobs, or list at $59 as a no-friction starter.
Difficulty & Ship Time
beginner · ships in 2-4h.