Getting started
This page takes a resource from nothing to a validated net event and a typed RPC, and lists every setting Rivo FX reads: convars, ACE permissions and editor types. Read Introduction first for what the library is.
1. Install the rivo_fx resource
Download rivo_fx.zip from the latest release and unzip it into your resources folder. The folder must be named rivo_fx. Start it before anything that uses it:
ensure rivo_fx
ensure my_shop
2. Load it in your resource
-- my_shop/fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
dependency 'rivo_fx'
shared_script '@rivo_fx/init.lua'
server_script 'server.lua'
client_script 'client.lua'
@rivo_fx/init.lua defines the global Fx in your resource's runtime. Core modules load at once; FiveM modules (Fx.net, Fx.rpc, Fx.assets, ...) load the first time you use them. Lua 5.4 (lua54 'yes') is required.
Or start from a template with the CLI (CLI):
npx @rivolabs/fx-cli create my_shop # server + client
npx @rivolabs/fx-cli create my_shop --template lua-nui # plus a NUI page
3. A validated net event
-- server.lua
local S = Fx.S
Fx.net.handle('shop:buy', S.struct { item = S.string:maxChars(32), qty = S.int:between(1, 10) },
function(src, input)
return Fx.logInfo('purchase', { player = src, item = input.item, qty = input.qty })
end)
-- client.lua
Fx.net.send('shop:buy', { item = 'water', qty = 2 })
The schema runs before the handler. A payload that fails it never reaches your code and is reported as a security event. Each player is limited to 10 calls per second per event unless you pass { rateLimit = '5/s' } (or false). See Net events and RPC.
4. A typed RPC
-- server.lua
local OutOfStock = Fx.TaggedError('OutOfStock')
local stock = { water = 3 }
Fx.rpc.register('shop:stock', { input = S.string:maxChars(32) }, function(src, item)
if (stock[item] or 0) == 0 then return OutOfStock { item = item }:fail() end
return stock[item]
end)
-- client.lua
Fx.runFork(Fx.rpc.call('shop:stock', 'water', { timeout = 5000 })
:map(function(n) print('in stock', n) end)
:catchTag('OutOfStock', function(e) print('sold out:', e.item) return Fx.unit end))
5. Editor types
Point LuaLS at the bundled type definitions, for example in .luarc.json:
{ "workspace.library": ["../rivo_fx/types"] }
Settings Rivo FX reads
| Setting | Kind | Default | What it does |
|---|---|---|---|
rivo_fx:logLevel |
convar | info |
debug, info, warn, error or none for Fx.log and the Fx.logInfo family |
rivo_fx:tracing |
convar | on |
off stops recording spans |
rivo_fx:metricsToken |
convar (server, use set, not setr) |
unset | turns on /rivo_fx/metrics and /rivo_fx/spans; requests need Authorization: Bearer <token> |
rivo_fx.devtools |
ACE | none | who may open /fxdev, e.g. add_ace group.admin rivo_fx.devtools allow |
See Metrics, tracing and logs and Devtools.
JavaScript and TypeScript resources
npm install @rivolabs/fx effect # resources, on the real Effect package
npm install @rivolabs/fx-nui # NUI pages
JS and Lua resources speak the same protocol: a Lua client can call a TypeScript RPC and the other way round, and typed errors cross both ways. See JS/TS and NUI.
Next
- New to effects: Effects, then Errors.
- Moving an existing resource: Moving a resource to Rivo FX.
- Copy-paste solutions: Recipes.