riptide/core
A lightweight and professional framework for Roblox.
Riptide was built from the ground up for production Roblox games. It solves the most common architecture problems while remaining invisible, staying out of your way, and scaling elegantly.
Warning
๐ Maelstrom Build โ Unstable
You are on the Maelstrom pre-release channel (0.9.0-maelstrom.1). Maelstrom is Riptide's unstable development branch โ it ships on a separate Git branch, is not production-tested, and APIs may change without notice. If you need stability, pin a stable release.
โจ Key Features
- ๐
Deterministic Lifecycle: Phased initialization (
InitโStart) ensures modules and plugins load in a predictable, race-free order. - ๐ Sandboxed Plugins: A complete
PluginManagerwith Kahn's topological sort, cycle detection, and isolated, crash-safe third-party plugins. - โก Zero-Allocation Signals: A synchronous linked-list signal dispatcher with zero scheduler overhead and no per-fire thread creation.
- ๐ก Unified Networking: Multiplexed
RemoteEventandUnreliableRemoteEventnetworking with flat, closure-free middleware chains. - ๐ก๏ธ Typed Remote Validation: Enforce client payload types at the network boundary via
Network.RegisterTyped()and composableGuardvalidators. - ๐ฆ 100% Strict Luau: Written entirely with
--!strict, exporting clean API interfaces for full autocomplete and type-checking. - ๐ ๏ธ Built-in Power: Ships with Sleitnick's
Troveresource tracker,EventBuspub/sub,Guardschema validators,StateMachine,Asyncutilities, and server-authoritativeStatereplication.
๐ฆ Installation
Via Pesde (Recommended)
pesde add riptide/core
Via Wally
[dependencies]
Riptide = "riptide/[email protected]"
Manual (.rbxm)
Download Riptide.rbxm from the Releases page and place it inside ReplicatedStorage.
๐ Quick Look
Riptide organizes your game logic into Services (server) and Controllers (client). Each module follows a clean two-phase lifecycle: Init runs synchronously before any module starts, and Start runs asynchronously afterward.
-- ServerScriptService/Services/CoinsService.lua
--!strict
local CoinsService = {}
function CoinsService:Init(Riptide)
-- Init runs synchronously. Register network handlers and grab
-- references to other services here โ everything is loaded but
-- not yet started.
Riptide.Network.RegisterTyped("BuyItem", {
Riptide.Guard.String(50), -- itemId: string, max 50 chars
Riptide.Guard.Number(0, 1000), -- price: number, 0โ1000
}, function(player, itemId, price)
print(player.Name .. " bought " .. itemId .. " for " .. price .. " coins")
end)
end
function CoinsService:Start(Riptide)
-- Start runs in its own coroutine โ safe to yield here.
self.Trove = Riptide.Trove.new()
print("CoinsService is running!")
end
function CoinsService:OnPlayerAdded(Riptide, player)
Riptide.State:SetForPlayer(player, "coins", 0)
end
return CoinsService
Launch the framework from a single server script:
-- ServerScriptService/main.server.lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Riptide = require(ReplicatedStorage.Packages.Riptide)
Riptide.Server.Launch({
ModulesFolder = ServerScriptService.Services,
})
๐งช Testing Architecture
Riptide ships with a Hybrid Testing Architecture built on frktest:
- CI / Development: 99 unit tests run via Lune CLI in milliseconds โ no Studio required.
- Engine Integration: The exact same suites compile and run inside a real Roblox DataModel for true Client/Server replication validation.
lune run test/lune/RunLuneTests.luau
๐ Documentation
Complete setup guides, API reference, and examples:
๐ License
MIT โ see LICENSE.