W-DevelopmentW-Development
Engineering Updated 9 min read

Designing a config.lua people can actually use

Design FiveM script configs well: config vs code, server-only secrets, naming, defaults, startup validation, framework switches and escrow-friendly configs.

Overview

The config is the part of your script every server owner touches. A good one makes installation boring — in the best way. A bad one produces support tickets, leaked webhooks and servers where a typo in a coordinate crashes the resource on start.

Shared vs server-only config

fxmanifest.lualua
shared_script 'config.lua'          -- sent to clients
server_script 'config_server.lua'   -- never leaves the server

escrow_ignore { 'config.lua', 'config_server.lua', 'locales/*.json' }

Everything in a shared or client file is downloaded by every player and readable. Discord webhooks, API keys and payout amounts belong in the server-only file — see anticheat basics.

A clear shape

config.lualua
Config = {}

Config.Debug = false
Config.Framework = 'auto'      -- 'auto' | 'esx' | 'qb' | 'qbx'
Config.Inventory = 'ox'        -- 'ox' | 'qb'

Config.Garages = {
    legion = {
        label = 'Legion Square',
        coords = vec3(215.8, -810.1, 30.7),
        spawn = vec4(229.7, -800.1, 30.5, 157.8),
        jobs = nil,                -- nil = everyone
    },
}

Config.Impound = {
    fee = 250,
    jobs = { police = 2 },     -- job = minimum grade
}
  • Group by feature, not by type.
  • Use vec3/vec4 for positions — readable and fast.
  • Keep English comments short and on the settings people change.
  • Avoid functions in configs unless they are explicit hooks (e.g. Config.CanUse = function(src) ... end).

Validate at startup

server.lualua
for id, g in pairs(Config.Garages) do
    assert(type(g.label) == 'string', ('Config.Garages.%s.label must be a string'):format(id))
    assert(type(g.spawn) == 'vector4', ('Config.Garages.%s.spawn must be vec4(x, y, z, heading)'):format(id))
end

A clear message at start beats a nil error an hour later in the middle of a scene. Annotate config shapes for editor help — see Lua annotations.

Defaults that work

Ship with coordinates, prices and toggles that work on a fresh server, Config.Debug = false, and translations in a locale file rather than in the config — see localization. Document every option in your README — see script documentation.

Frequently asked questions

What should go in a FiveM config.lua?

Values server owners change: locations, prices, jobs, toggles. Logic stays in code.

Where should I put webhooks and API keys?

In a server-only config file loaded with server_script, never in shared or client files.

How do I keep configs editable in escrowed resources?

List them in escrow_ignore in the fxmanifest.

Should configs contain translations?

Better in locale files, so translators do not need to touch the config.

Need this built, not just explained?

Premium ESX, QBCore & Qbox scripts with instant delivery — or a custom resource, React NUI and the web stack around your server, built to spec.

Related guides