Hey everyone!
Ive been working on my own framework for a while and finally decided to share it. I got tired of rewriting the same stuff (networking, player data, module loading) for every new project, so I built this for myself. Maybe someone else will find it useful
Its pretty simple. You split your code into modules with lifecycle hooks, and the framework handles the rest: dependency injection, player/character events, heartbeat updates, and network contracts
This is a solo project built from scratch to solve my own workflow needs. Its not a clone of anything - just my personal take on a lightweight framework
Quick Start: Install the Nextinel Builder Plugin to auto-generate the folder structure, typed modules, and update existing framework scripts in one click
Example (server code):
So instead of writing manually
local players = game:GetService("Players")
function CharacterAdded(character: Model)
local humanoid = character:WaitForChild("Humanoid")
local root = character:WaitForChild("HumanoidRootPart")
...
end
function PlayerAdded(player: Player)
player.CharacterAdded:Connect(CharacterAdded)
end
players.PlayerAdded:Connect(PlayerAdded)
You can write it that way:
local replicatedStorage = game:GetService("ReplicatedStorage")
local Types = require(replicatedStorage.Modules.Global.Types)
return {
characterLoaded = function(character, humanoid, root, player)
...
end,
} :: Types.ServerModule
No need to call WaitForChild manually - the framework waits for the Humanoid and RootPart to exist before calling this hook
Under the hood
- Nextinel Builder: Studio plugin for one-click setup and generating typed modules
- Type Safety: Built-in
Types.ServerModuleandTypes.ClientModulefor full IntelliSense on all hooks - Error Tracebacks: Filtered
xpcalltracebacks that point directly to your module, hiding framework internals - Heartbeat buckets: To update modules across 3 buckets so it doesnât lag
- Jolt API: For networking, with
Network contractsfor runtime type validation - DataStoreService: Built on
ProfileStorewith Migrator, typed profiles, and:observe()methods - HangWatcher: Warns if a moduleâs
inittakes longer than 10s - Dependency Injection: Modules declare dependencies, resolved with priority
Why Nextinel?
Unlike heavier frameworks, Nextinel gives you a lightweight base. You get the routine handled for you, but you keep full control over your architecture. No bloat, no magic
Known Limitations
Note: Dependencies are still string-based for simplicity (dependencies = {"ModuleName"} ). This means dependingServices wonât have autocomplete inside init(), but all lifecycle hooks are now fully typed
Full API Reference
Server module hooks:
return {
dependencies = {"ModuleName"}, -- optional
priority = 0, -- optional
skipHangWatch = false, -- optional
init = function(dependingServices) end,
update = function(deltaTime) end,
playerAdded = function(player) end,
playerDataLoaded = function(player, profile) end,
playerRemoving = function(player) end,
characterAdded = function(character, player) end,
characterLoaded = function(character, humanoid, root, player) end,
characterAppearanceLoaded = function(character, player) end,
humanoidAdded = function(humanoid, player) end,
characterRemoved = function(character, player) end,
onServerLowMemory = function() end,
onServerRestartScheduled = function(restartTime, source, attributes) end,
bindToClose = function(source) end,
network = {
-- optional: incoming events
remote = {
channel = "ChannelName",
shouldCheckExtrafields = false, -- optional (default: true)
contract = {[1] = "string", [2] = "number"}, -- optional
onEvent = function(player, name, count) end,
},
-- optional: incoming requests
invoke = {
channel = "InvokeChannel",
shouldCheckExtrafields = false, -- optional (default: true)
contract = {[1] = "string", [2] = "number"}, -- optional
onInvoke = function(player, ...) return end,
},
},
}
Client module hooks:
local channels = {}
--[[
-- Client channel methods:
channels.ChannelName:fireServer(...)
channels.ChannelName:fireServerUnreliable(...)
local result = channels.ChannelName:invoke(...)
]]
return {
dependencies = {"ModuleName"}, -- optional
priority = 0, -- optional
skipHangWatch = false, -- optional
init = function(dependingServices) end,
asyncInit = function() end, -- runs asynchronously (wrapped in task.spawn)
update = function(deltaTime) end,
clientReady = function() end,
characterAdded = function(character) end,
characterLoaded = function(character, humanoid, root) end,
humanoidAdded = function(humanoid) end,
characterRemoved = function(character) end,
network = {
-- optional: incoming events
remote = {
channel = "ChannelName",
shouldCheckExtrafields = false, -- optional (default: true)
contract = {[1] = "string", [2] = "number"}, -- optional
onEvent = function(name, count) end,
},
-- optional: incoming requests
invoke = {
channel = "InvokeChannel",
shouldCheckExtrafields = false, -- optional (default: true)
contract = {[1] = "string", [2] = "number"}, -- optional
onInvoke = function(...) return end,
},
},
setupFireServer = {
channelsNames = {"ChannelName", "InvokeChannel"},
setupChannel = function(name, networkObject)
channels[name] = networkObject
end,
},
}
Note: asyncInit is called before init and runs asynchronously, so it doesnât block the main thread
Updates (Posts)
v1.1.0 Network changes: Click
v1.1.1 Logger & Types: Click
v2.0.0 DataStore Module Rework: Click
v2.1.0 HangWatcher, Priorities & Profile Methods: Click
v2.2.0 Nextinel Builder & Type Safety: Click
v2.3.0 Core Stability & Safety Update: Click
v2.4.0 Memory Awareness: Click
v3.0.0 Network API Rework & Server Hooks: Click
GitHub
I put full docs and installation instructions in the README. Download link is in Releases
GitHub Repo
Also here you can find a Demo place