A Roblox Studio plugin that turns selected Instances into readable source that recreates them. It can emit plain Luau, plain roblox-ts, React in Luau, React in roblox-ts, React JSX, Fusion in Luau, Fusion in roblox-ts, and Fusion JSX from the same selection.
- Generate plain Luau, plain roblox-ts, React Luau, React roblox-ts, React JSX, Fusion Luau, Fusion roblox-ts, or Fusion JSX output for a single Instance or a multi-Instance selection.
- Walk descendants (toggle), respect
Archivable, and skip properties that match class defaults to keep output short. - Per-class property allowlist covering common
BasePart,Model, GUI, layout, light, value, sound, and particle classes. - Datatype literals for
Vector2/Vector3,UDim/UDim2,Color3,BrickColor,CFrame,EnumItem,NumberSequence,ColorSequence,Rect, andNumberRange. - Stable, deterministic variable naming with collision handling and two
identifier styles (
camelCase,snake_case). - Three root strategies: parent roots to
script.Parent, return a table of roots from abuild()function, or leave roots unparented. - Scrollable output view inside the plugin widget so long files stay usable in smaller dock sizes.
rokit installThis pulls rojo, stylua, and selene at the versions pinned in
rokit.toml.
-
Build the plugin file:
rojo build default.project.json -o Blueprint.rbxm
-
Move
Blueprint.rbxminto your local Studio plugins folder:- Windows:
%LOCALAPPDATA%\Roblox\Plugins - macOS:
~/Documents/Roblox/Plugins
- Windows:
-
Restart Studio. A Blueprint button appears under the Plugins tab. Click it to open the dock widget.
For a faster iteration loop, run rojo serve default.project.json and use the
Rojo Studio plugin's "Sync into Studio" option to push the source directly
into a place. Wrap the resulting model in a Script parented to
ServerScriptService if you want to exercise it without packaging.
The test place includes representative fixtures (parts, a nested model with duplicate child names, a GUI tree) plus a small spec runner.
rojo build test.project.json -o BlueprintTest.rbxlxOpen BlueprintTest.rbxlx in Studio. On run:
Workspace.BlueprintFixturesis populated.- The spec runner under
ServerScriptService.BlueprintTests.specsprints[PASS]/[FAIL]lines for each test.
You can also poke at the modules from the command bar:
local Blueprint = game.ServerScriptService.Blueprint
print(require(Blueprint.Generator).generate(game:GetService("Selection"):Get(), {}).source)For day-to-day iteration, run rojo serve test.project.json and use the
Rojo plugin to sync into an empty baseplate.
src/
init.server.luau plugin bootstrap (toolbar, button, dock widget)
Config.luau defaults and persisted setting keys
UI/ widget UI (vanilla Roblox Instances)
Selection/ Studio selection observer
Generator/ orchestration, naming, traversal, property allowlist
Serializer/ value -> Luau expression
Formatter/ indented line buffer
Util/ small shared helpers
test/
fixtures.server.luau builds a sample tree in Workspace
specs/ runner + spec modules
| Option | Effect |
|---|---|
| Include descendants | Walk children recursively from each selected root. |
Respect Archivable |
Skip Instances (and their subtrees) where Archivable is false. |
| Only changed properties | Compare to Instance.new(class) defaults; skip matches. |
| Schema | Switches between plain Luau, plain roblox-ts, React Luau, React TS, React JSX, Fusion Luau, Fusion TS, and Fusion JSX. |
| Naming | Variable casing for generated locals. |
| Root parent | How to parent the top-level Instances in the output. |
- All
BasePartsubclasses with common positional, visual, and physics props. Model,Folder,Attachment,Decal,Texture, lights.- GUI:
Frame,TextLabel/Button/Box,ImageLabel/Button,ScrollingFrame,UICorner,UIStroke,UIPadding, layouts, and size constraints. Sound,ParticleEmitter,Beam.ValueBase(StringValue,IntValue, etc.) via theValueproperty.- Schema targets:
plain Luau with
Instance.new, plain roblox-ts withnew Instance(...), React Luau withReact.createElement(...), React roblox-ts withReact.createElement(...), React JSX with tag syntax, Fusion Luau withNew(...), Fusion roblox-ts withNew(...), and Fusion JSX with tag syntax.
- Reference properties (e.g.
ObjectValue.Value,Beam.Attachment0/1) that point at Instances outside the emitted subtree are skipped rather than guessed at. In plain Luau and roblox-ts, references to emitted descendants are deferred until the target variable exists. Fusion and React still skip instance-reference properties. - Scripts (
Script,LocalScript,ModuleScript) are intentionally skipped: theirSourceis not readable from non-Command-Bar plugins without script injection permission, and silently emitting empty scripts would be misleading. - Services and other non-
Instance.new-creatable classes are reported in the status bar and skipped.
Add an entry to BASES in src/Generator/PropertyMap.luau. Each entry lists
the ancestor class and the properties to consider. Properties are filtered
through Serializer.canSerialize at emission time, so adding an unsupported
datatype to the list will simply produce a warning rather than break output.
To add a new datatype, register a formatter in src/Serializer/Literals.luau
or src/Serializer/TypeScriptLiterals.luau and wire it into the dialect table
in src/Serializer/init.luau.