Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/rojo-rbx/rojo/llms.txt

Use this file to discover all available pages before exploring further.

Rojo uses a set of rules to decide which Roblox instance type to create from each file on disk. When you run rojo serve or rojo build, every file in your project’s tree is matched against these rules in order, and the first match determines how the file is converted.

Default sync rules

The table below lists all built-in rules. Rules are matched top-to-bottom; more specific patterns (like *.server.lua) appear before broader ones (like *.lua) to ensure they take priority.
File patternRoblox instanceNotes
*.server.lua / *.server.luauScript (ServerScript)Server-side scripts
*.client.lua / *.client.luauLocalScript (ClientScript)Client-side scripts
*.plugin.lua / *.plugin.luauPluginScriptStudio plugin scripts
*.lua / *.luauModuleScriptShared modules
*.project.json / *.project.jsoncNested projectEmbeds another Rojo project
*.model.json / *.model.jsoncJSON modelRoblox instance tree encoded as JSON
*.json (not *.meta.json)ModuleScriptJSON parsed to a Lua table returned by require()
*.jsonc (not *.meta.jsonc)ModuleScriptSame as above with comment support
*.tomlModuleScriptTOML parsed to a Lua table returned by require()
*.csvLocalizationTableLocalization data
*.txtStringValuePlain text string value
*.rbxmxRoblox XML modelRoblox XML model file
*.rbxmRoblox binary modelRoblox binary model file
*.yml / *.yamlModuleScriptYAML parsed to a Lua table returned by require()
*.meta.json and *.meta.jsonc files are reserved for Rojo metadata. They are not turned into instances. See the meta files reference for details.

How instance names are derived

For most files, Rojo strips the full suffix defined by the rule to produce the instance name. For example, PlayerController.server.luau becomes a Script named PlayerController. For plain *.lua / *.luau files, only the extension is stripped: Utils.luau becomes a ModuleScript named Utils.

Init files and directory promotion

When a directory contains a file named init.lua, init.luau, init.server.lua, init.server.luau, init.client.lua, init.client.luau, or init.csv, the directory itself becomes that instance type instead of becoming a Folder. All other files inside the directory become children of that instance. This is the standard pattern for scripts that also need child instances.
src/
  Inventory/
    init.lua          ← Inventory becomes a ModuleScript
    ItemSlot.lua      ← child ModuleScript named "ItemSlot"
    Config.lua        ← child ModuleScript named "Config"
src/
  GameManager/
    init.server.lua   ← GameManager becomes a Script
    Rounds.lua        ← child ModuleScript named "Rounds"
The priority order for init files (highest to lowest) is:
  1. default.project.json / default.project.jsonc — makes the directory a nested project
  2. init.luau / init.luaModuleScript
  3. init.server.luau / init.server.luaScript
  4. init.client.luau / init.client.luaLocalScript
  5. init.csvLocalizationTable
If none of these files are present, the directory becomes a Folder.
Prefer .luau over .lua for new files. Roblox’s Luau language uses .luau as its canonical extension, and Rojo treats both equivalently.

Custom sync rules

You can add entries to the syncRules field in your project file to handle file patterns that Rojo does not recognize by default, or to override the default behavior for a specific extension. Each rule has three fields:
pattern
string
required
A glob pattern relative to the project file’s directory. Matched against file paths.
use
string
required
The middleware to use when the pattern matches. Must be one of the camelCase middleware names from the table below.
suffix
string
The suffix to strip from the file name to produce the instance name. If omitted, only the file extension is stripped.

Available middleware names

use valueProduces
serverScriptScript (ServerScript)
clientScriptLocalScript (ClientScript)
moduleScriptModuleScript
pluginScriptPluginScript
projectNested project
jsonModelJSON model
jsonStringValue
tomlStringValue
csvLocalizationTable
textStringValue
rbxmxRoblox XML model
rbxmRoblox binary model
yamlStringValue
ignore(ignored, no instance created)

Example: custom rule for data files

default.project.json
{
  "name": "my-game",
  "tree": {
    "$className": "DataModel",
    "$path": "src"
  },
  "syncRules": [
    {
      "pattern": "*.data.json",
      "use": "json",
      "suffix": ".data.json"
    },
    {
      "pattern": "*.spec.luau",
      "use": "ignore"
    }
  ]
}
In this example, PlayerData.data.json becomes a StringValue named PlayerData, and any *.spec.luau file is silently skipped.
Custom rules defined in syncRules take priority over the default rules. If a file matches a custom rule, the default rules are not checked.

Middleware and the emitLegacyScripts flag

By default (emitLegacyScripts: true), *.server.lua / *.server.luau files produce a Script and *.client.lua / *.client.luau produce a LocalScript — the classic Roblox class types. Setting emitLegacyScripts: false switches to the newer behavior where both produce a Script instance with the RunContext property set to Server or Client respectively. See Configuring your project file for details.

Build docs developers (and LLMs) love