Skip to content

Roblox

pesde can be used in Roblox projects, however this requires some extra setup. Namely, you need to specify a roblox_sync_config_generator script in order to generate the adequate configuration for the sync tool you are using.

The pesde-scripts repository contains a list of scripts for different sync tools. If the tool you are using is not supported, you can write your own script and submit a PR to get it added.

Usage with Rojo

Rojo is a popular tool for syncing files into Roblox Studio.

Running pesde init will prompt you to select a target, select roblox or roblox_server in this case. You will be prompted to pick out a scripts package. Select pesde/scripts_rojo to get started with Rojo.

Usage with other tools

If you are using a different sync tool, you should look for it’s scripts package on the registry. If you cannot find it, you can write your own and optionally submit a PR to pesde-scripts to help others using the same tool as you get started quicker.

Scaffold your project with pesde init, select the roblox or roblox_server target, and then create a .pesde/roblox_sync_config_generator.luau script and put it’s path in the manifest.

Authoring packages

When authoring packages for Roblox, it is recommended to have your code inside of a src directory (or any other directory you prefer).

Inside of your pesde.toml you must specify the roblox environment and the lib field with the path to your main script. You must also specify a list of build_files. This list should contain names of top level files or directories that should be synced into Roblox by a sync tool, such as Rojo.

Let’s say you have a package with the following structure:

  • Directoryroblox_packages/
    • dependency.luau
  • Directorysrc/
    • init.luau
    • foo.luau
    • bar.luau
  • LICENSE
  • pesde.toml
  • README.md
  • selene.toml
  • stylua.toml

There are lots of files in the root directory that are not needed in Roblox, such as configuration files, READMEs, and licenses. We only want the src and the roblox_packages directory to be synced into Roblox.

  • Directoryroblox_packages/
    • dependency (roblox_packages/dependency.luau)
  • Directorysrc/ (src/init.luau)
    • foo (src/foo.luau)
    • bar (src/bar.luau)

This is where build_files come in, we can specify a list of files that should be synced into Roblox. In this case, we only want the src directory to be synced. We do not need to specify the roblox_packages directory, as it is always synced.

So for our package, the pesde.toml file would roughly look like this:

pesde.toml
name = "acme/package"
version = "1.0.0"
license = "MIT"
includes = [
"pesde.toml",
"LICENSE",
"README.md",
"src/**/*.luau",
]
[target]
environment = "roblox"
lib = "src/init.luau"
build_files = ["src"]
[dependencies]
dependency = "acme/library"

When a consumer of your package installs it, the roblox_sync_config_generator script they are using will generate the configuration needed for their sync tool. For example, a Rojo user would get a default.project.json with the following contents:

default.project.json
{
"tree": {
"src": {
"$path": "src"
},
"roblox_packages": {
"$path": "roblox_packages"
}
}
}

The linker scripts that pesde generates will then point to the src module.

Then, to publish your package, you can follow the steps in the “Publishing Packages” guide.

Test place with Rojo

You might want to create a “test place” where you can test your package inside Roblox, or to get proper LSP support when developing your package.

To do this, you can create a test-place.project.json file which includes your package and the roblox_packages directory.

test-place.project.json
{
"tree": {
"$className": "DataModel",
"ReplicatedStorage": {
"package": {
"$className": "Folder",
"src": {
"$path": "src"
},
"roblox_packages": {
"$path": "roblox_packages"
}
}
}
}
}

You can then run rojo serve with this project file:

Terminal window
rojo serve test-place.project.json

If you are using Luau LSP you can change the luau-lsp.sourcemap.rojoProjectFile extension setting to test-place.project.json to get proper LSP support when developing your package.

Differences from Wally

Those coming from Wally may be a bit confused by the way pesde handles Roblox packages.

In Wally, it is standard to have a default.project.json with the following:

{
"tree": {
"$path": "src"
}
}

This will cause the src directory to be directly synced into Roblox.

In pesde, you should not have a default.project.json file in your package. Instead, you are required to use the build_files field to specify a 1:1 match between Roblox and the file system. These are given to the roblox_sync_config_generator script to generate the configuration for the sync tool the user is using. pesde forbids default.project.json to be part of a published package, as well as ignoring them from Git dependencies. This allows the consumer of your package to choose the sync tool they want to use, instead of being constrained to only using Rojo as well as preventing broken packages from being published (for example, if the project is configured as a DataModel).

This has the effect that the structure of the files in the file system ends up being reflected inside Roblox.

With Wally, the structure that ends up in Roblox ends up looking like this:

  • DirectoryPackages/
    • Directory_Index/
      • Directory[email protected]/
        • Directorypackage/ (src/init.luau)
          • foo (src/foo.luau)
          • bar (src/bar.luau)
        • dependency

Whereas with pesde, it looks like this:

  • Directoryroblox_packages/
    • Directory.pesde/
      • Directoryacme+package/
        • Directory1.0.0/
          • Directorysrc/ (src/init.luau)
            • foo (src/foo.luau)
            • bar (src/bar.luau)
          • Directoryroblox_packages/
            • dependency (roblox_packages/dependency.luau)

The roblox_server target

Although optimizing your server-only dependency using the roblox_server target might sound like a good idea it is not recommended, since it complicates linking and makes your package unnecessarily harder to use. On a public registry it is also redundant, since the package can be downloaded by anyone. Syncing the scripts to the client may also come up as a reason, but it is a micro-optimization which is very hard to observe, so it is unnecessary.

The target exists for a reason, that is private registries. You might want to have internal packages, such as configs or otherwise sensitive code which you do not want clients to see. This is where the roblox_server target comes in handy. If you’re not using a private registry you should use the standard roblox target instead.