TutorialServer
Where tutorial progress becomes something you can save.
Require it directly
const TutorialServer = require(Packages.TutorialKit.Server)
Never reach it through the kit's facade. require(Packages.TutorialKit) pulls the spotlight, the
pointer and ezvisualz, none of which have any business running on a server.
Step 1 — start the bridge at boot
Do this before any client can report, otherwise early reports are lost.
TutorialServer:Start()
Step 2 — save what the client reports
TutorialServer.PlayerStepAdvanced:Connect(function(player, step, previousStep)
DataService:Set(player, "TutorialStep", step)
end)
TutorialServer.TutorialCompleted:Connect(function(player)
DataService:Set(player, "TutorialDone", true)
end)
Step 3 — put returning players back where they were
Players.PlayerAdded:Connect(function(player)
if DataService:Get(player, "TutorialDone") then
TutorialServer:Complete(player)
return
end
const saved = DataService:Get(player, "TutorialStep")
if saved then
TutorialServer:SetStep(player, saved)
end
end)
The direction of authority
The client reports what it did; it never dictates what happens next. The server is the only side that decides, and TutorialServer:SetStep is how it says so.
Everything arriving from a remote is parsed and dropped when malformed, so neither side ever sees a bad packet. A client can still lie about which step it reached, so treat these signals as progress tracking, not as a place to hand out rewards.
Properties
PlayerStepAdvanced
eventsFires when a player reports reaching a step. The third argument is the step they came from, and is nil on the first one.
TutorialServer.PlayerStepAdvanced:Connect(function(player, step, previousStep)
DataService:Set(player, "TutorialStep", step)
end)
Steps the server itself ordered with TutorialServer:SetStep do not come back through here, so this never echoes your own decisions.
TutorialCompleted
eventsFires once when a player walks past the last step.
Functions
Start
lifecycleTutorialServer:Start() → ()Creates the kit's RemoteEvent and starts listening.
Call it once during server boot. Reports that arrive before this are lost, and since a client only reports after its own tutorial starts, "before boot finishes" is a real window.
The kit carries its own RemoteEvent, so it needs no slot in your network layer.
Errors
| Type | Description |
|---|---|
| "TutorialKit.Server is server only" | Called from a client |
Stop
lifecycleTutorialServer:Stop() → ()Disconnects and forgets tracked progress. Rarely needed outside tests.
SetStep
TutorialServer:SetStep(step: number--
Order number to put them on
) → ()Puts a client on a given step.
This is the server telling the client where to be, and it is how you resume a returning player
from saved data. It requires the client's tutorial to have been built with Replicate = true.
Errors
| Type | Description |
|---|---|
| "TutorialKit.Server is server only" | Called from a client |
Complete
Ends a client's tutorial, for instance when saved data says they already finished it.
Errors
| Type | Description |
|---|---|
| "TutorialKit.Server is server only" | Called from a client |
GetStep
TutorialServer:GetStep() → number?--
Last step they reported, or nil
Reads tracked progress without a round trip.
This is in-memory only and is cleared when the player leaves, so it is a convenience for save hooks, not a substitute for your data store.