§ How to · with Picoo
How to make a notification system in Roblox
By Sametcan Tasgiran, Founder & Developer·Published ·Updated
The moment two things happen at once, an unqueued notification system draws both in the same place and you lose one of them.
Notifications are a queue with a renderer — and the queue is the part everyone skips.
Queued, not stacked
Bursts of events line up and play in order instead of drawing on top of each other.
Types with styles
Info, success, warning and reward each read differently at a glance.
Server-triggered
One remote any server system can fire — the client owns rendering.
Deduplication
Repeats within a short window collapse into a counter rather than five identical toasts.
Priority
Critical messages jump the queue; cosmetic ones drop when the queue is long.
Phone-safe layout
Anchored and scaled so toasts do not sit under the Roblox top bar or off the screen.
Files Picoo ships for this prompt
2 files · 150 lines · ~25s · 1 credit
NotifyClient
Queue, dedupe, priority, tween in/out, layout.
105 lines
NotifyService
Server API and the single remote everything fires through.
45 lines
Sample output: StarterPlayerScripts.NotifyClient
-- Without a queue, two events in the same frame render two toasts in the same
-- position and the player sees one. The queue is the system; the tween is decor.
local queue: { Notification } = {}
local showing = false
local function pump()
if showing or #queue == 0 then return end
showing = true
local n = table.remove(queue, 1) :: Notification
local toast = build(n)
toast.Parent = gui
tween(toast, IN):Play()
task.delay(n.duration, function()
local out = tween(toast, OUT)
out.Completed:Once(function()
toast:Destroy()
showing = false
pump() -- next one only after this one has left
end)
out:Play()
end)
end
-- Dedupe: "+1 coin" fired forty times is one toast with a count, not forty
-- toasts. Collapse on identical text inside a short window.
local DEDUPE_WINDOW = 2
function Notify.push(n: Notification)
local last = queue[#queue]
if last and last.text == n.text and os.clock() - last.at < DEDUPE_WINDOW then
last.count += 1
return
end
n.at, n.count = os.clock(), 1
if n.priority == "critical" then table.insert(queue, 1, n) else table.insert(queue, n) end
pump()
endBuilding a notification system in Roblox
Notifications are the system people write in ten minutes and then quietly rewrite three times.
The first version creates a frame, tweens it in, waits, tweens it out. It works perfectly while you are testing one event at a time. Then a player picks up a coin, levels up and completes a quest within the same second, and all three toasts are created at the same anchored position — so the player sees one and never learns about the other two. The fix is not better animation; it is a queue. Show one, wait for it to leave, show the next. That single change is the difference between a demo and a system.
The second rewrite comes from spam. A collection event that fires per item produces a toast per item, and a good pickup streak turns the screen into a wall. Collapsing identical messages that arrive close together into one entry with a count keeps the information and drops the noise.
The third is about priority, and it shows up once you have enough notification types to conflict. A cosmetic "+1 coin" should never delay "your base is under attack". Two lanes — critical goes to the front of the queue, cosmetic gets dropped when the queue is long — cost almost nothing and prevent the case where important information arrives eight seconds late.
Structurally, keep the split clean: one remote carrying a type and a message, and a client module that owns everything visual. Server systems then announce things without knowing anything about GUI, and changing how notifications look never means touching gameplay code.
See more on the Luau generator, the game builder, or browse the full blog.
Frequently asked
Should notifications live on the server or the client?+
The client renders them; the server only says what happened. Keeping GUI code on the server is impossible anyway, but the useful part is the split: one RemoteEvent that any server system fires with a type and a message, and one client module that decides how it looks. Adding a new notification later becomes a one-line server call.
Why do my notifications overlap?+
There is no queue. Two events in the same frame each create a toast at the same anchored position, and the player only ever sees the top one. A queue that shows the next notification after the previous one has finished leaving fixes it, and it is maybe fifteen lines.
How do I stop notification spam?+
Collapse repeats. If the same text arrives again within a couple of seconds, increment a counter on the pending entry instead of queueing another. Picking up forty coins should read as one toast saying forty, not forty toasts.
Can I use Roblox's built-in notification?+
StarterGui:SetCore("SendNotification", ...) exists and is fine for a quick prototype. It gives you no control over style, position or queueing, and it looks like a system message rather than part of your game — so it is a stopgap, not a system.
Where should toasts appear?+
Away from the Roblox top bar and away from the mobile joystick and jump button. Top-centre and bottom-right are both safe; top-left collides with the Roblox UI and bottom-left sits under the thumbstick on phones.
Related Picoo prompts
main menu and loading screen in Roblox
Both are one property and one location — and once they are right, the rest is layout.
Roblox quest system
9 files · 310 lines · 1m 18s · 1 credit. ProfileService-style save flow.
Roblox daily rewards
5 files · 170 lines · 49 seconds · 1 credit. 7-day cycle by default, configurable.