Getting Started¶
This guide installs Vanguard, creates a server service and client controller, and starts both runtimes.
Requirements¶
- Roblox Studio
- A Rojo project
- Wally
0.3.x - Vanguard
0.1.15
Vanguard is dependency-free. Its utility modules are included in the package.
Install with Wally¶
Add Vanguard to the game project's wally.toml:
Install dependencies:
Map the generated Packages directory into ReplicatedStorage:
{
"name": "MyGame",
"tree": {
"$className": "DataModel",
"ReplicatedStorage": {
"Packages": {
"$path": "Packages"
}
}
}
}
Prefer a direct require path. It preserves Vanguard's exported Luau types for Studio autocomplete:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Vanguard = require(ReplicatedStorage.Packages.Vanguard)
If the package must be awaited, retain its static type explicitly:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Packages = ReplicatedStorage:WaitForChild("Packages")
local Vanguard = require(Packages:WaitForChild("Vanguard") :: ModuleScript)
:: typeof(require(ReplicatedStorage.Packages.Vanguard))
Recommended Layout¶
src
server
Bootstrapper.server.luau
Services
GreetingService.luau
client
Bootstrapper.client.luau
Controllers
GreetingController.luau
shared
Classes
Components
Plugins
The exact folders are not required. Bootstrap accepts any Instance containing ModuleScripts.
Create a Service¶
Create GreetingService.luau on the server:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Vanguard = require(ReplicatedStorage.Packages.Vanguard)
local GreetingService = Vanguard.CreateService({
Name = "GreetingService",
Client = {
Greeted = Vanguard.CreateSignal(),
},
})
function GreetingService.Client:Greet(player, name)
local message = self.Server:BuildGreeting(name)
self.Greeted:Fire(player, message)
return message
end
function GreetingService:BuildGreeting(name)
return `Hello, {name}!`
end
function GreetingService:VanguardStart()
self.Logger:Info("Greeting service ready")
end
return GreetingService
Anything in Client becomes a remote visible through a client service proxy:
- Functions become remote methods.
CreateSignal()becomes a two-way reliable event.CreateUnreliableSignal()becomes an unreliable event when Roblox supports it.CreateProperty(value)becomes a server-owned replicated property.CreateReplicator(table)becomes a server-owned replicated state tree.
Start the Server¶
Create Bootstrapper.server.luau:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Vanguard = require(ReplicatedStorage.Packages.Vanguard)
Vanguard.Bootstrap({
Plugins = ReplicatedStorage.Shared.Plugins,
Services = script.Parent.Services,
Options = {
LogLevel = "info",
},
}):catch(function(err)
warn(`Vanguard server failed: {err}`)
end)
Bootstrap loads every descendant ModuleScript in Services, registers valid service definitions, and calls Start.
Create a Controller¶
Create GreetingController.luau on the client:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Vanguard = require(ReplicatedStorage.Packages.Vanguard)
local GreetingController = Vanguard.CreateController({
Name = "GreetingController",
})
function GreetingController:VanguardStart()
local GreetingService = Vanguard.GetService("GreetingService")
GreetingService.Greeted:Connect(function(message)
self.Logger:Info(message)
end)
GreetingService:Greet("Builder"):andThen(function(message)
self.Logger:Info(`Server returned: {message}`)
end):catch(function(err)
self.Logger:Warn(err)
end)
end
return GreetingController
Remote service methods return Vanguard promises by default. Remote signals use Connect, Once, and Wait like local signals.
Start the Client¶
Create Bootstrapper.client.luau:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Vanguard = require(ReplicatedStorage.Packages.Vanguard)
Vanguard.Bootstrap({
Plugins = ReplicatedStorage.Shared.Plugins,
Controllers = script.Parent.Controllers,
Options = {
LogLevel = "info",
},
}):catch(function(err)
warn(`Vanguard client failed: {err}`)
end)
What Happens During Startup¶
- ModuleScripts are required and registered.
- plugin init hooks run.
- On the server, remote Instances and network guards are built.
- service/controller
VanguardInithooks run and must complete. - plugin start hooks run.
- service/controller
VanguardStarthooks are scheduled. - registered components begin watching CollectionService tags.
- the
StartorBootstrappromise resolves.
Start hooks are scheduled but not awaited. Use init hooks for work that must finish before the framework becomes ready.
Next Steps¶
- Read Lifecycle before adding dependencies between systems.
- Add server boundary checks using Network Security.
- Learn the full Services and Controllers APIs.
- Use Components for tagged instance behavior.
- Use Plugins for diagnostics, extension hooks, and project-level tooling.
- Use Replicators for server-owned structured state.
- Review the Troubleshooting checklist when Studio reports a startup error.