Try it in your browserpreview Source

Compiling and nodemaps for Roblox✎

How a graph becomes a file, and a file becomes an instance in Studio.

Verified

This page is about graphs whose Target is Roblox. The bar along the top of the canvas says which, and a new graph takes the project's. For Lune, the answer is a different one and it is on Compiling and nodemaps for Lune.

A graph is a .nodescript under .roswaal/scripts. Compiling it writes a .luau file to the same place under src, and Rojo syncs that into Studio. Roswaal never talks to Studio itself.

Folders carry across: .roswaal/scripts/ReplicatedStorage/Shared/Greeter.nodescript writes src/ReplicatedStorage/Shared/Greeter.luau. Both directories are project settings.

Nodemap basics

Here is the whole of it. A .nodemap is edited in Roswaal rather than as JSON by hand, and this is that editor — the tree on the left, the Inspector on the right, and the project file it writes underneath. Every part is named beside it; the rest of this page explains them in order.

Tycoon
▸DataModelDataModel
▸ReplicatedStorage
SharedFoldersrc/Shared
▸ServerScriptService
ServerFoldersrc/Server

This map

Instance

Ignore paths

Globs under this instance's path that Rojo should skip, e.g. shared/** — how you stop a nested mapping syncing twice.

Project file

Written to default.project.json when this map is compiled.

Project-wide ignores

Passed to Rojo as globIgnorePaths, unanchored.

{  "name": "Tycoon",  "tree": {    "$className": "DataModel",    "ReplicatedStorage": {      "Shared": {        "$path": "src/Shared"      }    },    "ServerScriptService": {      "Server": {        "$path": "src/Server"      }    }  }}
  • The treeEvery instance the map describes. Pick one and the Inspector follows.
  • DescribesWhether this is a DataModel for Roblox or a filesystem for Lune. It decides what the rest of the panel is.
  • NameThe instance's name in the DataModel.
  • ClassBlank on a service, because Rojo infers it from the key and rejects it being said twice.
  • PathThe folder or file on disk whose contents fill this instance.
  • Ignore unknownRojo leaves alone anything in Studio that it did not put there.
  • Ignore pathsGlobs under this instance's path that Rojo should skip.
  • Add folder, Add service, DeleteBuild the tree. Services can only be added to the root.
  • OutputWhere the project file is written, relative to the project root.
  • Project-wide ignoresPassed to Rojo as globIgnorePaths, unanchored.
  • The project fileWhat the map compiles to. Selecting a row lights the lines that row writes.
The real panel. Select a row and the Inspector fills with that instance's fields, while the project file scrolls to the lines the row writes. A row lights its own lines and not its children's — they are rows too. The fields are filled rather than editable: this is the editor demonstrating itself, not a scratch project.

What a graph compiles to

The file is named after the graph, and its ending comes from the script kind, chosen in the tools along the top of the canvas. The ending is how Rojo knows which class of instance to make.

KindFileIn Studio
ScriptGreeter.server.luauA Script, running on the server
LocalScriptGreeter.client.luauA LocalScript, running on a player's machine
ModuleScriptGreeter.luauA ModuleScript, run by whatever requires it

Compiling

What it compiles
Compile script, or Ctrl + SThe open graph
Compile projectEvery graph, then every node map
Compile: DynamicEach graph as you edit it, and any that change on disk — after a git pull, say
roswaal compileEverything, or the one graph or map you give it
roswaal watchThe same, without the editor

A graph with errors writes nothing; warnings do not stop it. With format on and StyLua on your PATH, the file is formatted as it is written.

Generated files

A generated file starts with a header naming its graph and a hash of what was written. Roswaal will not overwrite a file whose hash no longer matches — one edited by hand — or a file it did not write.

Danger

To overwrite one anyway, click overwrite in the compile results, or run roswaal compile --force. The hand edit is lost.

Moving and deleting graphs

Rename a graph, move it or change its kind, and its next compile removes the file it used to write.

A generated file whose graph is gone is stale, and Rojo goes on syncing it. The compile results list stale files with a remove link. From the command line, roswaal prune lists them and roswaal prune --yes removes them.

Building a node map

A .nodemap says where your files land in the DataModel, and compiles to a Rojo project file — default.project.json unless you change it. You edit the tree in Roswaal rather than the JSON by hand.

Two things in that file are worth naming, because both are Roswaal leaving something out on purpose. A service carries no $className, because Rojo already knows what ReplicatedStorage is and saying it again is something Rojo rejects. And Shared is a Folder in the tree with no $className in the file, because a path pointing at a directory already implies one.

Make a map with New map in the toolbar, or by right-clicking a folder in the project tree. It starts with src in ServerScriptService. Select an instance to edit it:

FieldWhat it does
NameThe instance's name in the DataModel
ClassBlank for a service, because Rojo already knows what ServerScriptService is. Otherwise Folder, Model, Configuration, ScreenGui, Part or Tool
PathThe folder or file on disk that fills the instance. Marked when Roswaal cannot find it
Ignore unknownRojo leaves alone anything in Studio that it did not put there
Ignore pathsFiles under the path that Rojo should skip. Start one with / to write it from the project root

Add folder and Add service build the tree. Under Project file, Output is where the file is written and Project-wide ignores go to Rojo as written. The JSON it will write is shown underneath, with anything wrong — an instance with no name, or two with the same one.

Info

A map is written only by Write project file, Compile project or roswaal compile — never by Dynamic. A project file Roswaal did not write needs --force.

Requiring a module

A map is also how Roswaal knows where a file ends up. Drag a graph or a .luau from the project tree onto the canvas, and it offers Require Module with the path filled in — src/ReplicatedStorage/Shared/Greeter.luau becomes ReplicatedStorage.Shared.Greeter — or Instance for a reference to it. If no map covers the file, it says so.

Last reviewed 11 September 2026 by @neopolitans