Places and Rojo projects✎

Bringing a game in from its Rojo project or its place, browsing the place, and writing scripts back into it.

Verified

Most games already exist as a Rojo project, a place file, or both. This page is how Roswaal takes either in, shows you the place, and writes your scripts back into it. How a graph compiles is on Compiling and nodemaps for Roblox.

Starting from a Rojo project

A project Rojo already manages has its tree in default.project.json. Project → Import Rojo project…, or roswaal import default.project.json, reads it into a node map beside your graphs. The file is not changed, and every field in it is kept, including ones the map editor has no control for.

orchard
▸DataModelDataModel
▸ReplicatedStorage
Sharedsrc/shared
PackagesPackages
▸ServerScriptService
Serversrc/server
▸StarterPlayer
▸StarterPlayerScripts
Clientsrc/client

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": "orchard",  "tree": {    "$className": "DataModel",    "ReplicatedStorage": {      "Shared": {        "$path": "src/shared"      },      "Packages": {        "$path": "Packages"      }    },    "ServerScriptService": {      "Server": {        "$path": "src/server"      }    },    "StarterPlayer": {      "StarterPlayerScripts": {        "Client": {          "$path": "src/client"        }      }    }  }}
  • 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.
A project file read into a map. Select a row for its fields; the project file beside it is the one the map writes, the same as the one it was read from.

It asks which. Project File Only is the map, and your Luau stays hand-written, as the tree already lists it. Project File + Luau as Graphs is the map and then every hand-written .luau in the folders the file syncs, read into graphs with one set of Import as graph settings. Wally's packages are left out, and the .luau files are not changed.

Browse…, Open .zip… and Open folder… offer the same when there is a project file no map writes, with a list to pick from when there are several. A place file in the zip or folder is found too.

When the map compiles back to the same project, the map writes the file from then on. Compiling leaves it alone until the map changes, and then keeps its indentation and line endings. If the map would write it differently, the file stays yours until you compile with force.

Starting from nothing

roswaal new, Create on the start page and New project… in the editor make a project with place.rbxl unless you say not to: the place Studio starts a new experience with. A 2048-stud Baseplate with its top at height 0, a 12-stud SpawnLocation standing on it at the centre, and Studio's sky, light and chat. Roswaal writes it itself rather than copying Studio's Baseplate template, and Studio makes the Camera and the Terrain when the file is opened. roswaal export writes the project's scripts into it, with the folders they need.

Starting from a place

roswaal import place.rbxl makes a new project from a .rbxl or .rbxlx. Scripts Rojo can sync go under src/, and every service in the node map it writes has Ignore unknown, so Rojo never removes a part it was not given. The place is copied into the project.

A script inside a part, a model or a GUI stays in the place: Rojo cannot sync it without owning its parent. --scripts all brings those out too, under place/, where Rojo does not look. Identical copies become one file unless you pass --no-merge.

In the web app, Project → Open place… does the same, and asks the same questions with the counts in front of you. The place is kept with the project, and Export includes it.

Browsing the place

When the project has a place, the Project panel switches between Files and DataModel. DataModel lists the place's instances as Studio's Explorer does: its usual services first, children by name, and empty services at the end. Filter by name, or by a class name typed in full.

The Project panel with DataModel chosen: the place, as Studio's Explorer lists it.

Hover a control or its row to light the other.

  • FilterLists what matches by name, or by a class typed in full, with where each one is.
  • Read againReads the place file again.
  • An instanceIts name and class. Double-click it, or double tap, for Properties.
  • A scriptColoured by kind, as the project tree colours it. Properties has Open for the file that writes it.

Double-click or double-tap an instance to open the Properties panel on the right: its properties, tags and attributes under Studio's headings. While it is open it follows what you pick, and a reference goes to what it names. For a script a project file writes, Open opens that file, and its graph when one generates it.

An instance opened from the DataModel, on the right under the Inspector.

  • CloseStops showing the instance.
  • The instanceDrag it onto a graph for an Instance node at its path.
  • A propertyDrag it onto a graph for a Get Member. Hold Ctrl as you drop for Set Property.
  • TagsThe instance's tags, as CollectionService reads them.
  • An attributeDrag it for Get Attribute, or Set Attribute with Ctrl.

Changing properties

Turn on Settings → Workspace → Modify DataModel Instances and Properties changes values as well as showing them. Click a value to type over it, tick a box, pick from a list, or pick a colour from its swatch. Enter writes it; Esc puts it back.

Each change is written into the place file straight away. The first one asks, and a copy of the file as it was goes in .roswaal/backups first, and again whenever the file has changed since Roswaal last wrote it.

Can be changedNot yet
True or false, numbers, text, enums, colours and BrickColors; vectors, sizes, UDims, UDim2s, ranges and rects, a field a component; CFrames, as a Position and an Orientation in degrees; and references, picked from the place's instances of the class they take. On properties a script can set. Attributes and tags too, added and removed with the + and × beside them, and names, on anything but a serviceScripts' source, which is the project's to write

Warning

Close the place in Studio first. Studio's next save puts back the values it has.

Dragging onto a graph

Drag from PropertiesWhat it makes
A propertyAn Instance node at the instance's path, cast to its class, wired into Get Member, typed as the property is
A property, with Ctrl held as you dropThe same, into Set Property. A read-only property stays a Get Member
An attributeGet Attribute, or Set Attribute with Ctrl
The instance's nameThe Instance node alone

An instance dragged from the DataModel list makes the Instance node alone too.

Dropped from Properties
Script StartInstanceInstanceWorkspaceInHouse.Do…Path.AnchoredPrintValue
Anchored, dropped: Get Member, typed boolean, printed here.
luau
local Workspace = game:GetService("Workspace")

print(Workspace.House.Door.Anchored)
Script StartInstanceInstanceWorkspaceInHouse.Do…PathSet PropertyInstanceAnchoredPropertyValue
The same drop with Ctrl held: Set Property.
luau
local Workspace = game:GetService("Workspace")

Workspace.House.Door.Anchored = false
Script StartInstanceInstanceWorkspaceInHouse.Do…PathGet AttributeInstanceIsOpenNamePrintValue
IsOpen, an attribute: Get Attribute.
luau
local Workspace = game:GetService("Workspace")

print(Workspace.House.Door:GetAttribute("IsOpen"))

Dragging into code

Drop an instance, a property or an attribute into Code Block's editor and it writes the Luau that reaches it, where you let go. The DataModel and Properties stay above the editor while it is open, to drag from.

Dropped onWhat it writes
A blank line of Code Blocklocal Tank = game:GetService("ReplicatedStorage").Tank
Anywhere else, or a box that holds one valueThe path alone

Writing scripts into the place

Export, beside Settings in the top bar, takes the project out as a zip, or its place file alone. Ctrl + Shift + E opens it too, and Project → Export… is still there. For a project with a place it says what Modify RBXL would write and add before you choose; Don't Modify RBXL sends the place as it was. The project's own place file is not changed either way. roswaal export out.rbxl writes the modified place to a file.

Save as writes the place as .rbxl, or as Legacy .rbxlx, whichever the project keeps. A place saved in the other format leaves out the kinds of property Roswaal cannot write yet, and the menu names them first. When a graph has changed since it was compiled, Compile first compiles it before the export. Ticked, Start with these choices keeps them in roswaal.json, and Settings → Compiling → Exporting shows them.

The Export button in the top bar, in a project with a place.

  • Project (.zip) | Place onlyThe whole project as a zip, or the place file alone.
  • NameThe file's name.
  • Compile first | Export as it isOffered when a graph has changed since it was compiled, which in Manual mode would otherwise export its old Luau.
  • Modify RBXL | Don't Modify RBXLModify writes the project's scripts into the copy of the place, and says how many; Don't sends the place as it was.
  • .rbxl | .rbxlx LegacyThe place's format. Legacy .rbxlx names any kinds of property Roswaal cannot write yet, which it leaves out.
  • Start with these choicesTicked, the menu opens with the same choices next time, for everyone who opens the project.
  • ExportDownloads it. The project's own files are not changed.

A script is found by the id the import recorded, or by its path, and a merged file is written into every copy. A file whose script is not in the place yet — a graph made since — is added, with a Folder for each part of its path the place does not have. Nothing else in the place changes.

Export saysWhy the file was not written
No service in the place forIts path starts at a service the place does not have
More than one script with that pathTwo siblings share a name, so which one is meant is not certain
A different kind of script in the placeModule code where the place has a Script, or the other way round
Still in the place, with no file nowThe file was removed or renamed. The script stays; delete it in Studio if it should go

Last reviewed 30 September 2026 by @neopolitans