--- alwaysApply: true --- # Atlas Project File Format > Atlas is a fork of Rojo. Many internal identifiers, API endpoints, and struct names still reference the original "Rojo" naming. ## Project File Schema **Recognized files:** `*.project.json5` (preferred) | `*.project.json` (legacy) **Special:** `default.project.json5` inherits parent folder name. | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | Yes* | Instance name (*optional if `default.project.json5`) | | `tree` | ProjectNode | Yes | Root instance tree structure | | `$schema` | string | No | JSON schema URL for editor validation (preserved during syncback roundtrip) | | `servePort` | number | No | Port for `atlas serve` (default: 34873) | | `serveAddress` | string | No | Address to bind (default: `"127.0.0.1"`) | | `servePlaceIds` | number[] | No | Only allow sync to these place IDs | | `blockedPlaceIds` | number[] | No | Block sync to these place IDs | | `placeId` | number | No | Set place ID on plugin connect | | `gameId` | number | No | Set game/universe ID on plugin connect | | `globIgnorePaths` | string[] | No | Glob patterns to ignore during sync | | `syncRules` | SyncRule[] | No | Custom file type mappings | | `syncbackRules` | SyncbackRules | No | Syncback configuration | | `syncScriptsOnly` | bool | No | Only sync script instances (default: false) | | `ignoreHiddenServices` | bool | No | Ignore internal services (default: true) | | `fileLogLevel` | string | No | File logging level: "trace" (default), "debug", "info", "warn", "error", "none" | ```json5 { "$schema": "https://raw.githubusercontent.com/UserGeneratedLLC/vscode-rojo/master/schemas/project.schema.json", "name": "MyProject", "tree": { /* ProjectNode */ }, "servePort": 34873, "serveAddress": "0.0.0.0", "servePlaceIds": [123456], "blockedPlaceIds": [111111], "placeId": 123456, "gameId": 789012, "globIgnorePaths": ["**/*.md", "**/node_modules/**"], "syncRules": [/* SyncRule */], "syncbackRules": { /* SyncbackRules */ }, "syncScriptsOnly": false, "ignoreHiddenServices": true, "fileLogLevel": "trace" } ``` ## ProjectNode Schema Used in `tree` and recursively for all children. | Field | Type | Description | |-------|------|-------------| | `$className` | string | Instance class (required for non-services) | | `$path` | string | Filesystem path to sync from | | `$id` | string | Unique ID for Ref property linking | | `$properties` | object | Instance properties to set | | `$attributes` | object | Instance attributes to set | | `$ignoreUnknownInstances` | bool | Whether to ignore instances not in project during sync | **Keys without `$` prefix are child instances.** ```json5 { "$className": "Folder", "$path": "src/MyFolder", "$id": "unique-id", "$properties": { "Anchored": true }, "$attributes": { "Health": 100 }, "$ignoreUnknownInstances": false, // Children "ChildFolder": { "$className": "Folder" }, "MyScript": { "$path": "src/MyScript.luau" } } ``` **Services auto-inferred:** Workspace, ReplicatedStorage, ServerScriptService, ServerStorage, StarterGui, StarterPlayer, Lighting, Teams, Chat, SoundService, LocalizationService, TestService, etc. ## File Extension Mappings ### Scripts | Extension | Result | RunContext | Note | |-----------|--------|------------|------| | `*.luau` | ModuleScript | — | Preferred | | `*.server.luau` | Script | Server | Preferred | | `*.client.luau` | Script | Client | Preferred | | `*.plugin.luau` | Script | Plugin | | | `*.local.luau` | LocalScript | — | | | `*.legacy.luau` | Script | Legacy | | | `*.lua` | ModuleScript | — | Legacy | | `*.server.lua` | Script | Legacy | Legacy | | `*.client.lua` | LocalScript | — | Legacy | | `*.plugin.lua` | Script | Plugin | Legacy | **Prefer `.luau`** — modern RunContext. `.lua` is legacy (still supported). ### Models & Data | Extension | Result | Note | |-----------|--------|------| | `*.rbxm` | Binary model | | | `*.rbxmx` | XML model | | | `*.model.json5` | JSON model | Preferred | | `*.model.json` | JSON model | Legacy | | `*.txt` | StringValue | | | `*.csv` | LocalizationTable | | | `*.json5` | ModuleScript (Lua table) | Preferred | | `*.json` | ModuleScript (Lua table) | Legacy | | `*.toml` | ModuleScript (Lua table) | | | `*.yaml`, `*.yml` | ModuleScript (Lua table) | | ### Meta & Project | Extension | Purpose | Note | |-----------|---------|------| | `*.meta.json5` | Add properties/attributes to sibling | Preferred | | `*.meta.json` | Add properties/attributes to sibling | Legacy | | `*.project.json5` | Nested project | Preferred | | `*.project.json` | Nested project | Legacy | ## Init File Priority When directory has multiple init files, first match wins: 1. `default.project.json5` → Nested project (preferred) 2. `default.project.json` → Nested project (legacy) 3. `init.luau` → ModuleScript (preferred) 4. `init.server.luau` → Script (Server) 5. `init.client.luau` → Script (Client) 6. `init.plugin.luau` → Script (Plugin) 7. `init.local.luau` → LocalScript 8. `init.legacy.luau` → Script (Legacy) 9. `init.csv` → LocalizationTable 10. `init.lua` → ModuleScript (legacy) 11. `init.server.lua` → Script (Legacy) 12. `init.client.lua` → LocalScript (legacy) **No init file?** → Directory becomes Folder. **Prefer `.luau` and `.json5` extensions.** ## Sync Rules Schema Custom file type handling in `syncRules` array: | Field | Type | Required | Description | |-------|------|----------|-------------| | `pattern` | string | Yes | Glob pattern to match files | | `use` | string | Yes | Middleware type (see table below) | | `suffix` | string | No | Extension to strip from instance name | | `exclude` | string | No | Glob pattern to exclude from matching | ```json5 { "syncRules": [{ "pattern": "*.foo", "use": "moduleScript", "suffix": ".foo", "exclude": "*.test.foo" }] } ``` ### `use` Values | Value | Result | |-------|--------| | `serverScript` | Script (Server) | | `clientScript` | Script (Client) | | `moduleScript` | ModuleScript | | `pluginScript` | Script (Plugin) | | `localScript` | LocalScript | | `legacyScript` | Script (Legacy) | | `json`, `toml`, `yaml` | ModuleScript | | `csv` | LocalizationTable | | `text` | StringValue | | `jsonModel`, `rbxm`, `rbxmx` | Instance tree | | `project` | Nested project | | `ignore` | Skip file | ## Syncback Rules Schema Configure `syncbackRules` object for Roblox → filesystem sync: | Field | Type | Default | Description | |-------|------|---------|-------------| | `ignoreTrees` | string[] | `[]` | Roblox tree paths to skip (e.g., `"ServerStorage/Secrets"`) | | `ignorePaths` | string[] | `[]` | Filesystem glob patterns to skip (e.g., `"src/generated/*"`) | | `ignoreProperties` | object | `{}` | Properties to skip per class: `{"ClassName": ["Prop1", "Prop2"]}` | | `ignoreClasses` | string[] | `[]` | Instance classes to skip entirely | | `syncCurrentCamera` | bool | `false` | Whether to sync `Workspace.CurrentCamera` | | `syncUnscriptable` | bool | `false` | Whether to sync unscriptable properties | | `ignoreReferents` | bool | `false` | Whether to skip Ref properties (e.g., `Model.PrimaryPart`) | | `createIgnoreDirPaths` | bool | `true` | Whether `/**` in ignore paths also matches the directory itself | | `ignoreHiddenServices` | bool | — | Override root-level `ignoreHiddenServices` for syncback | | `warnDuplicateNames` | bool | `false` | Warn on duplicate child names during syncback | ```json5 { "syncbackRules": { "ignoreTrees": ["ServerStorage/Secrets", "Workspace/Camera"], "ignorePaths": ["src/generated/*", "src/temp/**"], "ignoreProperties": { "BasePart": ["Color", "BrickColor"], "Script": ["Disabled"] }, "ignoreClasses": ["Terrain", "Camera"], "syncCurrentCamera": false, "syncUnscriptable": false, "ignoreReferents": false, "createIgnoreDirPaths": false, "warnDuplicateNames": false } } ``` ## Meta Files Add metadata to file-based instances. Meta files use **camelCase keys** (no `$` prefix -- that's only for ProjectNode). **Adjacent meta** (e.g. `MyScript.server.meta.json5` for `MyScript.server.luau`): ```json5 { "name": "Key:Script", // Override filename-derived instance name (slugify support) "id": "unique-id", // For Ref property linking "properties": { "Disabled": false }, "attributes": { "Priority": 1 }, "ignoreUnknownInstances": true } ``` **Directory meta** (e.g. `init.meta.json5` inside a directory): ```json5 { "name": "My:Folder", // Override directory-derived instance name "className": "Configuration", // Override class (directory meta only) "id": "unique-id", "properties": { "Anchored": true }, "attributes": { "Health": 100 }, "ignoreUnknownInstances": false } ``` **Key differences from ProjectNode:** Meta uses `className`, `properties`, `attributes` (camelCase, no `$` prefix). Adjacent meta does NOT support `className`. **`name` field (slugify support):** When an instance name contains forbidden filesystem characters (`: / ? * < > | " \`), or is the reserved name `"init"` (case-insensitive, slugified to `"init_"`), syncback slugifies the filename (forbidden chars → `_`) and stores the real name in the `name` field. On forward sync, `name` overrides the filename-derived instance name. On collisions (e.g. `A/B` and `A_B` both slugify to `A_B`), `~2`, `~3` suffixes are appended and meta `name` fields distinguish them. **`Rojo_Ref_*` attributes:** Meta files may also contain `Rojo_Ref_PropertyName` attributes written by syncback/two-way sync for Ref property linking. These are managed automatically and should not be hand-edited. Meta files also support a `$schema` field (preserved during syncback roundtrip). **Meta files CAN'T:** Set `$path`, have children. ## Model.json5 Format Inline instance definition. Like meta files, model files use **camelCase keys** (no `$` prefix). ```json5 { "name": "What?Model", // Override filename-derived name (slugify support) "className": "Tool", "id": "unique-id", "properties": { "CanBeDropped": false }, "attributes": { "Damage": 50 }, "children": [ { "name": "Handle", "className": "Part", "properties": { "Size": [1, 1, 3] } } ] } ``` **Note:** `children` is an **array** of child objects (each with a `name` field), not a map/object keyed by name. This differs from ProjectNode where children are flattened as keys. ## Property Formats ### Shorthand (Recommended) ```json5 { "$properties": { "Anchored": true, // Bool "Health": 100, // Number "Position": [0, 5, 0], // Vector3 "ImageRectSize": [100, 100], // Vector2 "Color": [1, 0, 0], // Color3 (normalized RGB) "BrickColor": "Bright red", // BrickColor name "Shape": "Ball", // Enum name "Tags": ["Collectible", "PowerUp"], // Array "Size": { "X": {"Scale": 1, "Offset": 0}, "Y": {"Scale": 0, "Offset": 100} }, // UDim2 "CFrame": { "position": [0, 5, 0], "orientation": [[1,0,0],[0,1,0],[0,0,1]] } // CFrame } } ``` ### Explicit Type Use when ambiguous or specifying enum by number: ```json5 { "$properties": { "Position": { "Vector3": [0, 5, 0] }, "Shape": { "Enum": 1 }, "BrickColor": { "BrickColor": 21 } } } ``` ## Attributes Same format as properties. Limitations: no Ref, no NumberSequence/ColorSequence, enums use string names only. ```json5 { "$attributes": { "Health": 100, "Position": [0, 5, 0], "MyFont": { "family": "rbxasset://fonts/families/SourceSansPro.json", "weight": "Regular", "style": "Normal" } } } ``` ## Ref Property Linking Two systems for linking instance references, both supported: ### Path-Based: `Rojo_Ref_*` (preferred, written by syncback/two-way sync) Uses filesystem-name paths (slugified, dedup'd) to reference target instances: ```json5 // In meta file for an instance with PrimaryPart pointing to Handle { "attributes": { "Rojo_Ref_PrimaryPart": "Workspace/MyModel/Handle.model.json5" } } ``` **Attribute format:** `Rojo_Ref_ = ""` Syncback writes **Luau-style relative paths**: - `@self` / `@self/Child.luau` -- target is same instance or a descendant - `./Sibling.luau` -- target is a same-parent sibling - `../Uncle.luau` -- target is a parent's sibling - `@game/Service/Path` -- cross-service reference Forward sync resolves both relative and absolute formats via `resolve_ref_path_to_absolute()` + `get_instance_by_path()`. Path segments use full filesystem names (slug + extension + dedup suffix), matched case-insensitive with instance name fallback. ### ID-Based: `Rojo_Target_*` + `$id` (legacy, still read by forward sync) Link instances via `$id` and special attributes: ```json5 { "tree": { "Target": { "$className": "Part", "$id": "myTarget" }, "Pointer": { "$className": "ObjectValue", "$attributes": { "Rojo_Target_Value": "myTarget" } } } } ``` **Attribute format:** `Rojo_Target_` **Priority:** When both `Rojo_Ref_*` and `Rojo_Target_*` exist for the same property, `Rojo_Ref_*` takes precedence. ## Property Types `String`, `Bool`, `Int32`, `Int64`, `Float32`, `Float64`, `Vector2`, `Vector3`, `Vector2int16`, `Vector3int16`, `UDim`, `UDim2`, `CFrame`, `Color3`, `Color3uint8`, `BrickColor`, `NumberRange`, `Rect`, `NumberSequence`, `ColorSequence`, `Enum`, `Ref`, `Content`, `Font`, `PhysicalProperties`, `Axes`, `Faces`, `Tags`, `Attributes` See `rbx_reflection_database` for property listings per class. ## Validation Errors 1. Unknown fields (except children) 2. Reserved names starting with `$` as children 3. Missing `$className` or `$path` 4. `$path` to non-existent file 5. Invalid property types 6. Invalid glob syntax 7. Duplicate `$id` ## Source Files - `src/project.rs` - Project parsing - `src/snapshot_middleware/mod.rs` - Extension mappings - `src/snapshot/` - Instance tree structure