<!-- fivemad.com, Markdown source of https://fivemad.com/docs/frameworks/esx -->
> Source: https://fivemad.com/docs/frameworks/esx
> Section: Frameworks
> Tags: esx, esx legacy, es_extended, framework, jobs, items, txadmin recipe, roleplay
> Last updated: 2026-09-22
> Site map for assistants: https://fivemad.com/llms.txt

# ESX Legacy quick start

Install ESX Legacy with the official txAdmin recipe, learn its structure, make yourself admin, add a job and an item in the database, write a small ESX script, avoid pitfalls.

ESX is the oldest of the big FiveM roleplay frameworks, and **ESX Legacy** is its current, maintained line. It has a huge catalogue of scripts and an official txAdmin recipe maintained by the ESX team. Official docs: [docs.esx-framework.org](https://docs.esx-framework.org).

[How to make an ESX FiveM Server! (HighwayTrooper)](https://www.youtube.com/watch?v=9UwKUztfVO8) (YouTube video)

## 1. Install with txAdmin

Requirements: an artifact, a license key, and **MariaDB**. The ESX docs are clear: use MariaDB only, not XAMPP, which they describe as outdated and known to cause data loss. See [Database setup](/docs/server-setup/database).

1. Start FXServer, link your Cfx.re account.
2. **Popular Recipes > ESX Legacy**.
3. License key and database connection (leave the name empty).
4. **Run Recipe** (the addons repository is big, so this step can take a while), then **Save & Run Server**.

What gets installed is listed in [Popular recipes](/docs/txadmin/popular-recipes#esx-legacy). The recipe's `server.cfg` sets game build `3258`, pma-voice settings and some security convars like `sv_filterRequestControl 2`.

## 2. The structure

```text
resources/
├─ [cfx-default]/
├─ [core]/            es_extended and the core ESX resources (from esx_core)
├─ [esx_addons]/      jobs, shops, society, vehicle shop and more (from ESX-Legacy-Addons)
└─ [standalone]/      oxmysql, ox_lib, pma-voice, bob74_ipl, phone
```

Start order in the recipe's `server.cfg`:

```cfg
ensure chat
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure [core]
ensure [standalone]
ensure [esx_addons]
```

ESX stores most data **in the database**: users, jobs, job grades, items, owned vehicles.

## 3. Make yourself admin

ESX has its own player groups (the `group` column of the `users` table), synced to ACE. The recipe's `server.cfg` lets `es_extended` manage principals, so ESX can put you in `group.admin` when your ESX group is admin.

1. Join the server once so your user row exists.
2. From the **server console** (txAdmin Live Console), set your group: `setgroup [your id] admin`.
3. Reconnect.

Alternatively, edit the `group` column for your row in the `users` table with HeidiSQL while you're offline. ESX's admin commands (`/car`, `/dv`, `/tp`, `/setjob`, `/giveitem`, `/noclip`...) then work for you. txAdmin's `/tx` menu works independently.

## 4. Add a job

Jobs live in two tables: `jobs` (name, label) and `job_grades` (job_name, grade, name, label, salary, skin_male, skin_female). Add them with SQL:

```sql
INSERT INTO `jobs` (`name`, `label`) VALUES ('burgershot', 'Burger Shot');

INSERT INTO `job_grades` (`job_name`, `grade`, `name`, `label`, `salary`, `skin_male`, `skin_female`) VALUES
  ('burgershot', 0, 'trainee', 'Trainee', 50, '{}', '{}'),
  ('burgershot', 1, 'cook', 'Cook', 75, '{}', '{}'),
  ('burgershot', 2, 'boss', 'Manager', 120, '{}', '{}');
```

Then reload jobs without a restart with the `refreshjobs` command (console or as admin), and assign it: `setjob [id] burgershot 2`. By ESX convention the top grade named `boss` gets the society boss menu in addons that support it.

## 5. Add an item

With the default ESX inventory, items are rows in the `items` table:

```sql
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES
  ('burger', 'Burger', 1, 0, 1);
```

Run `refreshitems`, then `giveitem [id] burger 1`. Make it usable in a server script:

```lua title="my_food/server.lua"
ESX.RegisterUsableItem('burger', function(source)
    local xPlayer = ESX.GetPlayerFromId(source)
    if not xPlayer then return end
    xPlayer.removeInventoryItem('burger', 1)
    TriggerClientEvent('esx_status:add', source, 'hunger', 200000)
    xPlayer.showNotification('You ate a burger')
end)
```

If you switched to **ox_inventory**, items are defined in `ox_inventory/data/items.lua` instead (same format as in the [Qbox quick start](/docs/frameworks/qbox#6-add-an-item-ox_inventory)). The [Inventory Icons](/tools/inventory-icons) tool makes transparent item images.

## 6. A small ESX script

```lua title="my_paycheck/fxmanifest.lua"
fx_version 'cerulean'
game 'gta5'

shared_script '@es_extended/imports.lua'
server_script 'server.lua'

dependency 'es_extended'
```

`@es_extended/imports.lua` gives your resource the `ESX` object. (The older way, `local ESX = exports['es_extended']:getSharedObject()`, also works.)

```lua title="my_paycheck/server.lua"
local lastClaim = {}

ESX.RegisterCommand('paycheck', 'user', function(xPlayer, args, showError)
    local id = xPlayer.getIdentifier()
    if lastClaim[id] and os.time() - lastClaim[id] < 3600 then
        xPlayer.showNotification('You already claimed it this hour', 'error')
        return
    end

    local job = xPlayer.getJob()
    local amount = 100 + (job.grade * 50)
    xPlayer.addAccountMoney('bank', amount, 'paycheck-bonus')
    lastClaim[id] = os.time()
    xPlayer.showNotification(('Paid $%d for %s'):format(amount, job.label), 'success')
end, false, { help = 'Claim a bonus paycheck (once per hour)' })
```

Useful `xPlayer` methods (from es_extended's player class): `getIdentifier()`, `getName()`, `getGroup()`, `getJob()`, `setJob(name, grade)`, `getMoney()`, `addMoney(amount, reason)`, `removeMoney(...)`, `getAccount('bank')`, `addAccountMoney(account, amount, reason)`, `getInventoryItem(name)`, `addInventoryItem(name, count)`, `removeInventoryItem(name, count)`, `canCarryItem(name, count)`, `showNotification(msg)`, `triggerEvent(name, ...)`. Server helpers: `ESX.GetPlayerFromId(src)`, `ESX.GetExtendedPlayers()`, `ESX.GetJobs()`, `ESX.RegisterUsableItem`, `ESX.RegisterCommand`.

## Common pitfalls

- **Old ESX tutorials**: code with `TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)` is from old ESX versions. Use `@es_extended/imports.lua` or the export.
- **Old addons**: many `esx_*` scripts on the internet target ESX 1.1 or 1.2 and use removed functions or `mysql-async`. oxmysql provides `mysql-async` compatibility, but test old scripts carefully.
- **XAMPP**: the ESX docs say not to use it.
- **Jobs not showing**: you inserted the SQL but didn't run `refreshjobs` or restart, or `job_grades.job_name` doesn't match `jobs.name`.
- **Money types**: cash is `money`, bank is the `bank` account, and some servers use `black_money`. Use `addAccountMoney` with the right account name.
- **Locale**: the recipe leaves `setr esx:locale` commented, so ESX uses the language picked in txAdmin. Uncomment and set it to override.

## Next steps

- Read [docs.esx-framework.org](https://docs.esx-framework.org) for es_extended's full API.
- Swap in ox_inventory if you want slot based inventory (see the ESX course videos in the [video archive](/docs/videos)).
