The Two Windows#
Job Center has two interfaces, one for people looking for work and one for the people hiring:
Window | Opened with | What it is for |
|---|---|---|
The job center | The clerk — the target option, or | Everyone. Browse the listings, apply, chat with employers, set a waypoint. |
The boss panel |
| Players whose current job and grade are listed as bosses. Read and answer applications. |
Both close with ESC or the ✕ in the top corner.
The Job Center#
The header carries a live count of active jobs: the players online right now who work one of the listed jobs. The sidebar starts with All Jobs and then shows every category, and picking one filters the cards.
A card shows the listing's picture with its status badge and icon, the title, the description and the salary. A red badge on a card counts the messages that employer has sent the player. Click a card for the details:
Part | What it shows |
|---|---|
Header | Title, company and icon — plus a chat button when the listing has |
Description · Salary | The listing's own text. |
Requirements · Benefits | One line per entry. |
Work Location | The name of the workplace. |
Apply for Job | Depends on the listing — see Applying for a Job below. |
Set Waypoint | Puts a GPS waypoint on the workplace and confirms |
Applying for a Job#
Each listing's applyType decides what Apply for Job does:
applyType | What happens | Needs |
|---|---|---|
| The player is hired on the spot, at grade | The listing's key must be a job your framework knows. |
| The chat with that employer opens. |
|
| The address opens in the player's web browser — a Discord invite, an application form. |
|
| No apply button: the listing informs and sets a waypoint. For activities nobody needs to be hired for. | — |
hasChatbox and applyType are independent: an instant job can still show the chat button, so a player can ask before taking it. Real Estate Agent and Tow Truck Operator ship that way.
The server checks the type. An instant hire requested for a listing that is not
"instant"is treated as an exploit, and the player is dropped withAttempted to exploit job hiring system.
The Chat#
Each player has one conversation per listing. The applicant writes from the job center; the bosses of that job read and answer from the boss panel.
Live in both directions. Every boss online is notified —
New message in <job> (n unread)— and the thread updates in their panel. The applicant is notified withNew reply from <job> (n unread)and the reply appears in their open chat.Offline applicants catch up. A reply sent while the applicant is away is announced on their next login, and the card carries a badge until they open the chat.
Anti-spam. Five seconds between messages, per sender. The window shows
Please wait before sending another messageand the server ignores anything faster.Names. Players online appear by character name. An applicant who is offline is listed as
Applicantplus the start of their identifier; a boss who is offline appears asBoss.
Chats live in the server's memory. A restart of the resource or the server clears them — see The Database.
The Boss Panel#
Opened with /jobchats (Config.BossCommand) or by using the boss tablet (Config.BossItem). Each one has its own switch, Config.UseBossCommand and Config.UseBossItem.
It lists the applicants of the job you hold, under that job's title: their name, the start of their last message and, while unread, the message count. Click one to open the thread — it is marked read for you, and every boss keeps their own read state.
The ✕ on an applicant closes the application: the thread is deleted for both sides, and that player can apply again from scratch.
Who is a boss#
bossGrades on each listing names the grades that may open the panel for that job:
bossGrades = {3, 4} -- grades 3 and 4 of this job, and nobody elseIt is an exact list, not a minimum.
{3}does not let grade 4 in. List every grade that should have access.Only the current job counts. A player on another job — or on this job at another grade — gets
You don't have access to this commandfrom the command andYou can't use this itemfrom the tablet.Grades are numbered as your framework numbers them. ESX and QBCore count from
0, the lowest rank.
Writing a Listing#
Every listing is one entry in Config.Jobs, in shared/config.lua. The key is the job's name in your framework — the name an instant hire sets, and the name a player's job is compared with for boss access.
Config.Jobs = {
police = { -- the framework's job name
title = 'Police Officer',
company = 'Los Santos Police Department',
icon = 'fas fa-shield-alt',
image = 'https://images.unsplash.com/photo-1568515387631-8b650bbcdb90?w=600&h=300&fit=crop',
salary = '$4,500 - $6,200',
status = 'High Demand',
category = 'emergency', -- a key of Config.JobCategories
description = 'Maintain law and order throughout the city.',
requirements = { 'Clean criminal record', "Valid driver's license" },
benefits = { 'Pension plan', 'Health insurance' },
location = 'Mission Row Police Station',
coords = vector3(428.23, -984.28, 30.71),
hasChatbox = true,
bossGrades = {3, 4},
applyType = 'chatbox', -- 'instant' · 'chatbox' · 'link' · 'hobby'
-- applyLink = 'https://discord.gg/yourserver', -- for 'link'
},
}Field | What it is |
|---|---|
| The job title on the card, in the chat header and in notifications. |
| The employer, under the title in the details. |
| A free Font Awesome 6 class, such as |
| A direct |
| Free text: the salary line, and the badge on the picture — High Demand, Commission Based, Now Hiring. |
| The key of a category in |
| The pitch, on the card and in the details. |
| Lists of lines. |
| The workplace's name, and the |
| Shows the chat button, and is required for |
| The grades that run the boss panel for this job. |
| How Apply for Job behaves, and the address for |
A listing's text is shown exactly as written — it is not translated through locales/. Write your listings in your server's language.
Categories#
Config.JobCategories = {
emergency = { label = 'Emergency Services', icon = 'fas fa-ambulance' },
business = { label = 'Business & Finance', icon = 'fas fa-building' },
-- the key is what a listing's category points to
}Ten ship — emergency, business, transport, service, entertainment, industrial, legal, medical, criminal and food. A category with no listings shows No jobs available in this category.
What ships#
24 listings, ready to edit or delete:
Category | Listings (key) |
|---|---|
Emergency Services | Police Officer ( |
Business & Finance | Bank Manager ( |
Transport & Logistics | Commercial Pilot ( |
Public Services | Auto Mechanic ( |
Entertainment & Media | News Reporter ( |
Industrial & Labor | Commercial Fisherman ( |
Legal & Government | Attorney ( |
Healthcare | Medical Doctor ( |
Underground | Product Distributor ( |
Food & Hospitality | Bartender ( |
Match the keys to your framework. The paramedic ships as
emsand the taxi driver astaxidriver, while stock ESX and QBCore call those jobsambulanceandtaxi. A key your framework does not know still shows in the job center, but it cannot hire anyone and nobody is its boss.
The Clerk and the Blip#
Config.JobCenterPed = {
model = 'a_f_y_business_01',
coords = vector4(-268.95, -956.13, 31.22, 204.35), -- x, y, z, heading
label = 'Open Job Center',
}
Config.JobCenterBlip = {
enabled = true,
coords = vector3(-268.95, -956.13, 31.22), -- keep it on the clerk
sprite = 407,
color = 3,
scale = 0.8,
name = 'Job Center',
shortRange = true, -- on the radar only when nearby
}The clerk is frozen in place, cannot be hurt and ignores what happens around it. Take coords where a player stands — the clerk's feet go one metre below that z — and use the fourth value to turn it towards the street. label is the text of the target option and of the prompt.
The blip has its own coords: move both when you move the clerk, or set enabled = false to keep the job center off the map.



