Migrating from Knit¶
Vanguard intentionally follows familiar Knit concepts while remaining dependency-free and adding components, class registries, scoped logging, configuration, caching, and server network guards.
This guide focuses on migration behavior rather than general Knit usage.
API Mapping¶
| Knit concept | Vanguard equivalent |
|---|---|
Knit.CreateService |
Vanguard.CreateService |
Knit.CreateController |
Vanguard.CreateController |
Knit.AddServices |
Vanguard.AddServices |
Knit.AddServicesDeep |
Vanguard.AddServicesDeep |
Knit.AddControllers |
Vanguard.AddControllers |
Knit.AddControllersDeep |
Vanguard.AddControllersDeep |
Knit.GetService |
Vanguard.GetService |
Knit.GetController |
Vanguard.GetController |
Knit.Start |
Vanguard.Start or Vanguard.Bootstrap |
Knit.OnStart |
Vanguard.OnStart |
KnitInit |
VanguardInit preferred; alias supported |
KnitStart |
VanguardStart preferred; alias supported |
| Provider-style extensions | Vanguard.CreatePlugin and plugin hooks |
Incremental Hook Migration¶
Existing hook names work:
Rename when convenient:
When both names exist for the same phase, Vanguard selects VanguardInit/VanguardStart first.
Service Migration¶
Typical change:
-- Before
local InventoryService = Knit.CreateService({
Name = "InventoryService",
Client = {},
})
-- After
local InventoryService = Vanguard.CreateService({
Name = "InventoryService",
Client = {},
})
Client method context remains familiar:
Vanguard provides self.Server only through the active remote call context and does not store a circular Client.Server field.
Controller Migration¶
Client GetService returns a Vanguard proxy. Remote methods return bundled Vanguard promises by default.
Audit promise APIs if existing code relies on methods beyond:
andThen;catch;finally;await.
The bundled Promise is intentionally small and has no cancellation, timeout, race, or retry helpers.
Startup Migration¶
Manual:
Recommended bootstrap:
Vanguard.Bootstrap({
Plugins = script.Parent.Plugins,
Services = script.Parent.Services,
Components = script.Parent.Components,
Classes = script.Parent.Classes,
Options = {
LogLevel = "info",
},
}):catch(warn)
Client uses Controllers.
Lifecycle Differences to Audit¶
- Service priority is built in; higher priorities initialize first.
- Equal-priority service init hooks run concurrently.
- Controller init hooks run concurrently.
- Start hooks are spawned and not awaited.
- Components start after start hooks are scheduled.
IsStartedmeans startup completed.
Do not rely on incidental module or alphabetical ordering for dependency completion.
Module Failure Isolation¶
Vanguard wraps each module require and automatic registration. One bad module logs an error and does not stop later modules from loading.
This improves resilience but can move the visible failure: startup may continue until another service tries to look up the skipped definition. Treat module-loader errors as primary failures and fix them before debugging missing dependencies.
Remote Signals, Properties, and Replicators¶
Define signals through Vanguard markers:
Client = {
Changed = Vanguard.CreateSignal(),
AimUpdated = Vanguard.CreateUnreliableSignal(),
State = Vanguard.CreateProperty("Loading"),
Snapshot = Vanguard.CreateReplicator({
Status = "Loading",
Items = {},
}),
}
Audit method names and behavior against Networking.
Remote properties are server-owned and support global/per-player values.
Replicators are server-owned structured state trees and require protocol 2.
Plugin Migration¶
Vanguard keeps services/controllers as the default architecture, but 0.1.15
adds plugins for extension-style concerns:
return Vanguard.CreatePlugin({
Name = "MigrationDiagnostics",
Runtime = "Shared",
Hooks = {
ServiceRegistered = function(context, payload)
context.Logger:Debug(payload.Name)
end,
},
})
Use plugins for diagnostics, custom registries, code generators, and project-level tooling. Keep authoritative gameplay state in services and client presentation in controllers.
Network Security Migration¶
Vanguard validates named network configuration at startup and runs guards before server remote handlers.
Add rules incrementally, starting with state-changing remotes:
local Validator = require(Vanguard.Util.Validator)
Network = {
Purchase = {
Validate = Validator.tuple(
Validator.string({ MinLength = 1, MaxLength = 64 }),
Validator.integer({ Min = 1, Max = 10 })
),
Authenticate = requireProfile,
Verify = verifyPurchase,
RateLimit = { Limit = 5, Window = 2 },
},
}
Validation does not replace checks inside authoritative mutation methods.
Logger Migration¶
Services and controllers receive self.Logger automatically:
Default startup logging is info. Set LogLevel = "debug" while migrating to see each registered object and lifecycle step.
Dependency Differences¶
Vanguard has no external Wally dependencies. Utilities are available under Vanguard.Util.
Replace project-specific imports only when desired; migration does not require adopting every Vanguard utility immediately.
Type Migration¶
Use Vanguard's exports:
type Service = Vanguard.Service
type Controller = Vanguard.Controller
type Promise = Vanguard.Promise
type RemoteSignal = Vanguard.RemoteSignal
type RemoteProperty = Vanguard.RemoteProperty
type Replicator = Vanguard.Replicator
type PluginDefinition = Vanguard.PluginDefinition
For specific service/controller fields, intersect custom shapes with base types. See Type System.
Suggested Migration Order¶
- Install Vanguard beside the existing package.
- Convert one isolated service and controller pair.
- Switch bootstrap for a test place or branch.
- Confirm init/start timing and client proxy behavior.
- Convert remaining services/controllers.
- Add network validators and rate limits.
- Adopt components/classes/utilities where they simplify existing code.
- Remove the old framework dependency after no modules require it.
Migration Checklist¶
- Every loaded ModuleScript returns exactly one value.
- Server and client require the same Vanguard package.
- Service and controller names remain unique.
- Required init work is in init hooks, not spawned start hooks.
- Client promise chains use supported methods.
- Server-only services are not looked up from the client.
- Client-facing remotes have validation and authorization policy.
- Wally and Rojo mappings point to the new package alias.
- Studio output shows Vanguard
0.1.15and protocol2on both runtimes.