Rojo with file-system routing

Professional-grade architecture for Roblox

Rogen is a superset of Rojo that generates Rojo project files from your file system. You organize your game by feature, and Rogen puts each file in the right place.

$rokit add ldgerrits/rogen@2.0.0-beta.1
Works with
~/game $ rogen serve┌ rogen serve · default.rogen.json│ ✔ Serving default.rogen.json with Rojo 7.7.1 at 127.0.0.1:34872.│ Studio connected to default.rogen.json.│
src/On disk
  • src/
  • └─ Inventory/
  • ├─ UI/
  • │ ├─ InventoryHud.luau
  • │ └─ ItemSlot.luau
  • ├─ InventoryController@Client.luau
  • ├─ InventoryInput@Client.luau
  • ├─ InventoryService@Server.luau
  • ├─ InventoryStore@Server.luau
  • ├─ InventoryTypes.luau
  • ├─ ItemCatalog.luau
  • └─ ItemIcons.rbxm
  • src/
  • └─ inventory/
  • ├─ ui/
  • │ ├─ inventory-hud.tsx
  • │ └─ item-slot.tsx
  • ├─ inventory-controller@client.ts
  • ├─ inventory-input@client.ts
  • ├─ inventory-service@server.ts
  • ├─ inventory-store@server.ts
  • ├─ inventory-types.ts
  • ├─ item-catalog.ts
  • └─ item-icons.ts
ExplorerRoblox Studio
  • ReplicatedStorage
  • Shared
  • Inventory
  • InventoryTypes
  • ItemCatalog
  • ItemIcons
  • UI
  • InventoryHud
  • ItemSlot
  • ServerScriptService
  • Inventory
  • InventoryService
  • InventoryStore
  • StarterPlayer
  • StarterPlayerScripts
  • Inventory
  • InventoryController
  • InventoryInput
  • ReplicatedStorage
  • shared
  • inventory
  • inventory-types
  • item-catalog
  • item-icons
  • ui
  • inventory-hud
  • item-slot
  • ServerScriptService
  • inventory
  • inventory-service
  • inventory-store
  • StarterPlayer
  • StarterPlayerScripts
  • inventory
  • inventory-controller
  • inventory-input

One folder per feature from server to client

01

Organize by feature

Keep everything a feature needs in one folder, from its server code to its UI and assets. You find it all in one place, and you remove a feature by deleting its folder.

See suggested architectures
src/
Combat/combat/
Inventory/inventory/
UI/ui/
InventoryHud.luauinventory-hud.tsx
ItemSlot.luauitem-slot.tsx
InventoryController@Client.luauinventory-controller@client.ts
InventoryService@Server.luauinventory-service@server.ts
InventoryTypes.luauinventory-types.ts
ItemIcons.rbxmitem-icons.ts
Shop/shop/
02

Enforce boundaries

Every require path includes the name of its feature, so a lint rule can stop one feature from reaching into another.

See the lint rule
requirebetween features
  • Inventory/inventory/Inventory/inventory/same feature
  • Combat/combat/Inventory/inventory/lint error
03

Multi-place games

Write shared code once and use it in every place. When one place needs its own version of a file, put a file with the same name in that place's folder, and it replaces the shared one.

Set up places
places/shared code, one override
shared/InventoryTypes.luauinventory-types.tsItemCatalog.luauitem-catalog.ts
lobby/uses the shared files
arena/ItemCatalog.luauitem-catalog.tsreplaces the shared one
04

Still Rojo

Run rogen serve where you ran rojo serve, with the same flags. Rojo still does the syncing and building underneath.

Coming from Rojo
  • $rogen serve
  • $rogen build -o game.rbxl
  • $rogen sourcemap -o sourcemap.json
  • $rogen syncback --input game.rbxl

How routing works

You choose the routes and where each one points. Add @Server@server to a file's name or put it in a Serverserver folder, and it goes to ServerScriptService. Files without a route go to *.

    The name InventoryService@Server.luau is read from src/Inventory, matched to the Server route in default.rogen.json, and written into default.project.json as InventoryService inside an Inventory folder. Rojo syncs it into Roblox Studio as ServerScriptService/Inventory/InventoryService, with an Inventory folder under each of the three services.

      src/On disk
      • src/
      • └─ Inventory/
      • ├─ UI/
      • │ ├─ InventoryHud.luau
      • │ └─ ItemSlot.luau
      • ├─ InventoryController@Client.luau
      • ├─ InventoryInput@Client.luau
      • ├─ InventoryService@Server.luau
      • ├─ InventoryStore@Server.luau
      • ├─ InventoryTypes.luau
      • ├─ ItemCatalog.luau
      • └─ ItemIcons.rbxm

      Mark only the files that belong on one side. Everything else goes to ReplicatedStorage through the * route.

      Result in Roblox StudioSame for both
      • ReplicatedStorage
      • Shared
      • Inventory
      • InventoryTypes
      • ItemCatalog
      • ItemIcons
      • UI
      • InventoryHud
      • ItemSlot
      • ServerScriptService
      • Inventory
      • InventoryService
      • InventoryStore
      • StarterPlayer
      • StarterPlayerScripts
      • Inventory
      • InventoryController
      • InventoryInput

      Built for agents

      Coding agents find their way around a feature as easily as you do.

      One feature, one folder

      When an agent works on a feature, everything it needs is in one folder, from server to client. It spends its context on your task instead of searching the codebase.

      Several agents at once

      Give each agent a feature. A lint rule catches any agent that makes one feature require another, and they never fight over a shared project file.

      Working with agents

      Used by Roblox studios

      “It has been a game changer for my team and I”

      Acecateer
      Technical Director, Wonder Works Studio

      “Spent the last couple days refactoring Lua Learning to use Rogen. I love it”

      Zack (boatbomber) Williams
      CEO, Torpedo Software
      $rokit add ldgerrits/rogen@2.0.0-beta.1