Roblox banned my asset for no reason, so you can download it as a file:
Link.rbxm (6.1 KB)
Logic:
You split all your systems into services (on the client, these are controllers), create a script to run “Link” on the client and server, and “Link” loads all modules by calling :init() on them
Interesting fact
- Link automatically removes GUI from the server, which reduces memory consumption
“Knit is depricated”
Knit is definitely depricated, but its architecture is not. Link makes organizing the architecture easier and faster
Documentation
Server and client core scripts example
- ServerLoader:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Link = require(ReplicatedStorage.Link)
Link.load(ServerScriptService.Services, function()
print("Server started")
end, warn)
- ClientLoader:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Link = require(ReplicatedStorage.Link)
Link.load(ReplicatedStorage.Controllers, function()
print("Client started")
end, warn)
Controller example
- TestController
local TestController = {}
function TestController:init()
print("Test controller loaded")
end
return TestController
Service example
- TestService:
local TestService = {}
function TestService:init()
print("Test service loaded")
end
return TestService
Networking (optional):
- Service:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Link = require(ReplicatedStorage.Link)
local TestService = {
client = {
Test = Link.createSignal(),
TestUnreliable = Link.createUnreliableSignal()
}
}
function TestService:init()
print("Test service loaded")
self.client.Test:connect(function(player: Player, data: any)
print("Received", data, "on server from", player)
end)
self.client.TestUnreliable:connect(function(player: Player, data: any)
print("Received", data, "on server from", player)
end)
end
return TestService
- Controller:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Link = require(ReplicatedStorage.Link)
local TestService = Link("TestService")
local TestController = {}
function TestController:init()
print("Test controller loaded")
TestService.Test:fire("Some data 1")
TestService.TestUnreliable:fire("Some data 2")
end
return TestController
Parallel?:
if you name module with .parallel on end like that it will run in parallel
secret features ![]()
- modules with names “JoinService” and “JoinController” will be loaded first
- you can change parallel tag by adding to workspace attribute with name “ParallelTag”
client = { Test = Link.createSignal(), }same asclient = { Test = Instance.new("RemoteEvent"), }

