Clean Architecture for Roblox Studio
In this tutorial you will build a complete coin game from scratch using this architecture. A player joins, their coins are loaded from DataStore, they earn one coin per second, and the balance is shown live in a UI label.
What you will build:
Player joins → data loads → coins shown in UI
Every second → +1 coin → UI updates live
Player leaves → data saves
Player rejoins → coins persist from last session
Before writing any code, set up the folder structure. Create the following instances in the Explorer panel. Every file marked as ModuleScript is a ModuleScript. The two Bootstrap files are Script and LocalScript respectively.
ReplicatedStorage/
└── Shared/ [Folder]
├── Framework/ [Folder]
│ ├── Signal [ModuleScript]
│ ├── ServiceLocator [ModuleScript]
│ ├── Context [ModuleScript]
│ ├── Cubit [ModuleScript]
│ └── NetBridge [ModuleScript]
└── Types/ [Folder]
└── PlayerTypes [ModuleScript]
ServerScriptService/
└── Server/ [Folder]
├── Bootstrap [Script] ← Script, not ModuleScript
├── Repositories/ [Folder]
│ └── PlayerRepository [ModuleScript]
├── Services/ [Folder]
│ └── DataService [ModuleScript]
└── Controllers/ [Folder]
└── PlayerController [ModuleScript]
StarterPlayerScripts/
└── Client/ [Folder]
├── Bootstrap [LocalScript] ← LocalScript, not ModuleScript
├── Cubits/ [Folder]
│ └── HUDCubit [ModuleScript]
└── Views/ [Folder]
└── HUDView [ModuleScript]
Roblox appends
.serverand.clientto Script and LocalScript names in some editors. In Studio, just name themBootstrapand make sure their instance type is correct.
Copy the five framework files verbatim. You can find the full source in Framework Files.
Shared/Framework/SignalShared/Framework/ServiceLocatorShared/Framework/ContextShared/Framework/CubitShared/Framework/NetBridgeOnce copied, do not modify them.
Create the following GUI hierarchy in StarterGui:
StarterGui/
└── MainGui [ScreenGui]
└── HUD [Frame]
└── CoinsLabel [TextLabel]
Position and style CoinsLabel however you like. The framework only cares that the path MainGui > HUD > CoinsLabel exists.
Next: Step 2 — Types