As far as I know, the intended way to store client-only code is either inside StarterPlayerScripts or StarterCharacterScripts. However, this has been rather painful for several reasons—especially when using a ModuleScript-only architecture:
- Autofill is broken because the modules are cloned and parented to
LocalPlayer.PlayerScriptsat runtime. - Require paths are convoluted compared to those used in
ServerScriptService. - Modules need to be wrapped in an additional folder just to avoid getting mixed up with Roblox’s default modules.
- Clicking on errors or prints doesn’t open the module after stopping the game.
- There’s a duplicate of all the modules under
StarterPlayerScripts. StarterPlayerScriptsis buried underStarterPlayer, making access less convenient.
Since there is no ClientScriptService, I had to get creative.
I didn’t want to pollute ReplicatedStorage with client-only code, so I used ReplicatedFirst instead. I’m aware of its technical quirks, but as far as I know, none of them are truly deal-breakers:
LocalScriptsinReplicatedFirstrun beforegame.Loaded—which is fine, because I only use ModuleScripts and start them with agame.Loadedcheck just in case.- I lose the built-in distinction between pre- and post-
game.Loadedcode—but I reintroduce this distinction with aReplicatedFirst.Introfolder, which usually only contains a single module anyway. - If I ever decide to add a custom loading screen, it might take slightly longer to appear, since it can only show up after all client code is loaded—but the delay is usually no more than 3 seconds.
Am I missing something here, or is this the new go-to?
