Description
A drop-in typed toast notification resource. It renders four styles —
success, error, info, warning — as stacked toasts via NUI, and exposes clean
exports so any other resource can fire a toast on the client
(exports['toasts']:notify(...)) or from the server to a specific player
(exports['toasts']:notifyPlayer(src, ...)). A server-wide notifyAll and a
/announce console command round it out.
Prompt Template
You are writing a FiveM resource for a generic toast notification system (no
framework dependency). Produce ONE file containing both client.lua and
server.lua, separated by clear "-- ===== client.lua =====" and
"-- ===== server.lua =====" banners.
CLIENT requirements:
1. A local notify(type, message, duration) that whitelists type against
{ success, error, info, warning } and falls back to "info" for anything else.
2. SendNUIMessage({ action='toast', type=, message=, duration= }).
3. exports('notify', notify) so other resources call
exports['{{RESOURCE}}']:notify('success', 'Saved!').
4. RegisterNetEvent('toasts:show', ...) as the SERVER->CLIENT bridge — without
this the server cannot reach the client.
5. A /testtoast command taking the type as arg[1].
SERVER requirements:
1. notifyPlayer(playerId, type, message, duration) -> TriggerClientEvent('toasts:show', playerId, ...).
2. notifyAll(...) using -1 as the target.
3. Export both; add an /announce CONSOLE-only command (source == 0).
Return only Lua. No prose, no markdown fences.
Expected Output
The reference Lua lives at content/expected-outputs/ui/02-notification-system.lua.
It implements the client notify with a type whitelist and exports('notify'),
the toasts:show net-event bridge, and server-side notifyPlayer / notifyAll
exports plus an /announce console command. In fxmanifest.lua it is a
client_script, a server_script, and a ui_page for the toast markup.
-- 02-notification-system.lua
-- Typed toast notification system (success / error / info / warning).
-- Client exposes an export + NUI bridge; server can push to any player.
-- ===== client.lua =====
-- Queue a typed toast onto the NUI layer.
local function notify(notifType, message, duration)
local valid = { success = true, error = true, info = true, warning = true }
if not valid[notifType] then
notifType = "info"
end
SendNUIMessage({
action = "toast",
type = notifType,
message = tostring(message),
duration = tonumber(duration) or 4000,
})
end
-- Export so other resources call exports['toasts']:notify('success', 'Saved!').
exports("notify", notify)
-- Server -> client bridge: a server script triggers this for a target player.
RegisterNetEvent("toasts:show", function(notifType, message, duration)
notify(notifType, message, duration)
end)
-- Quick test command so you can verify each style in-game.
RegisterCommand("testtoast", function(_, args)
local t = args[1] or "info"
notify(t, "This is a " .. t .. " toast.", 4000)
end, false)
-- ===== server.lua =====
-- Server-side helper: push a typed toast to a specific player id.
local function notifyPlayer(playerId, notifType, message, duration)
if not playerId then return end
TriggerClientEvent("toasts:show", playerId, notifType, message, duration)
end
-- Export it so server resources call exports['toasts']:notifyPlayer(src, ...).
exports("notifyPlayer", notifyPlayer)
-- Broadcast a toast to everyone (e.g. server announcements).
local function notifyAll(notifType, message, duration)
TriggerClientEvent("toasts:show", -1, notifType, message, duration)
end
exports("notifyAll", notifyAll)
-- Example: announce server-wide via a console/admin command.
RegisterCommand("announce", function(source, args)
if source ~= 0 then return end -- console only
notifyAll("warning", table.concat(args, " "), 8000)
end, true)
Known Failure Modes
- Missing net-event bridge — Claude writes the server
TriggerClientEventbut noRegisterNetEvent('toasts:show')client-side, so nothing fires. - Unvalidated type — passing the raw type into a class name lets a typo kill
styling; whitelist and fall back to
info. - Wrong export syntax — FiveM uses
exports['name']:fn(...), notexports.name.fn(...). - Spammy toasts — without a duration cap a flood of toasts stacks forever;
pass and respect a
duration.
Integration Notes
- Split the banners into real
client.luaandserver.luafiles; list both infxmanifest.luaalong with theui_pageandfiles {}. - No framework needed — works on ESX, QBCore or standalone.
- Test:
/testtoast success,/testtoast error, then from another resource callexports['toasts']:notify('info','hi')to confirm cross-resource use.
Profit Potential
$100–$1200/mo on Tebex (expected ~$300). [INFERRED] low end of the $50-389 band (signal-scraper tebex_snapshot, median seller $11.85K/mo, n=100); typed-toast systems are a commodity yet every resource needs one, so steady low-ticket volume.
Trend Signal
→ stable — [INFERRED] HUD/UI utilities are always-needed but commoditized.
Sales Angle
Position as drop-in notification infrastructure other resources depend on — framework-agnostic and bundle-friendly. Recommend $59 on Tebex.
Difficulty & Ship Time
beginner · ships in 2-4h.