> For the complete documentation index, see [llms.txt](https://studio-docs.sandbox.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://studio-docs.sandbox.game/best-practices/project-structure.md).

# Project Structure

A well-structured project is one where you and the AI can find anything in seconds. Poor structure does not cause immediate problems. It accumulates them: sessions where the AI reads the wrong files, features built in the wrong place, assets that cannot be found, and a codebase that becomes harder to navigate as it grows. Setting the structure up correctly at the start costs almost nothing. Fixing it mid-project costs significantly more.

## **The Core Explanation**

### **Start with Git: before anything else**

Before you write a line of code or place an asset, initialise a Git repository. Git is your undo button for the whole project. Not just individual files, the entire project, at any point in time. Every time you complete a working feature, commit it. That commit becomes a checkpoint you can return to if the next session goes wrong.

This matters more in AI-assisted development than anywhere else. The AI can make sweeping changes across multiple files in a single session. Without version control, a session that goes wrong can leave the project in a state that is difficult to manually reverse. With it, you roll back to the last known-good commit and try again.

{% hint style="info" %}
*NOTE: Commit after every verified feature, not every session. A commit should represent a working state. Half-finished work that compiles but does not run correctly is not a checkpoint worth keeping.*
{% endhint %}

Your project ships with a `.gitignore` the SDK maintains. Do not rewrite it. It already excludes everything regenerable:

* `node_modules/`, `.dist/`, `.editor/`, `.engine/` — restored by `pnpm install` or the next build
* `.cursor/mcp.json` — your personal editor connection details; never commit these

Everything else is committed, **including your scene files and prefabs**. `assets/` is the heart of your project — if it is not in Git, your levels are not backed up.

### **How a project is organised**

Every Sandbox Studio project has the same skeleton. You will spend nearly all your time in two folders:

| Folder    | What goes there                                      |
| --------- | ---------------------------------------------------- |
| `src/`    | Your TypeScript game code                            |
| `assets/` | Scenes, prefabs, materials, textures, models, sounds |

The rest is managed for you:

| Path                                  | What it is                                           | Rule                                        |
| ------------------------------------- | ---------------------------------------------------- | ------------------------------------------- |
| `YourProject.genesys-project`         | Project settings: default scene, engine version      | Leave it alone unless you know why          |
| `src/auto-imports.ts`                 | Generated list registering your game classes         | **Never edit** — regenerated on every build |
| `src/game-data.ts`                    | Generated editor metadata for your classes           | **Never edit**                              |
| `.engine/`                            | A read-only copy of the engine source, for reference | Read it, never change it                    |
| `.dist/`, `.editor/`, `node_modules/` | Build output and dependencies                        | Ignore entirely                             |

{% hint style="info" %}
*NOTE: If a change you made disappears after a build, check whether you edited a generated file. Generated files are overwritten every build; your code belongs in your own files under `src/`.*
{% endhint %}

### **Organising your code**

Group `src/` by what things are in your game, not by engine type. A layout that scales well:

```
src/
  Characters/     # pawns, controllers, enemy classes
  Gameplay/       # pickups, triggers, doors
  Behaviours/     # reusable behaviours shared across nodes
  UI/             # HUD and menu code
  Core/           # game mode, match flow, tuning
  game.ts         # entry point — don't move it
```

{% hint style="success" %}
*TIP: When you are about to create a new file and are not sure where it belongs, ask the AI: "Where in this project structure should a file that does X live?" Giving it the folder map above as context will produce a consistent answer.*
{% endhint %}

### **Naming conventions: make the type readable from the name**

Names should tell you what something is without opening the file.

| Kind                | Convention                          | Example                       |
| ------------------- | ----------------------------------- | ----------------------------- |
| Scene node classes  | PascalCase, named for the thing     | `HealthPickup`, `PatrolDrone` |
| Reusable behaviours | PascalCase + `Node` or a clear role | `CameraShakeNode`             |
| UI classes          | PascalCase + `UI` or widget name    | `ScoreboardUI`                |

Every class you place in a scene needs the registration decorator:

```typescript
@ENGINE.GameClass()
export class HealthPickup extends ENGINE.SceneNode { ... }
```

Custom classes always use `@ENGINE.GameClass()` — never `EngineClass`, which is reserved for the engine itself.

### **Asset structure: organised by type, not by feature**

Assets live in `assets/` and should be separated by type. This is the convention the engine expects and what the AI will search when looking for existing assets.

```
assets/
├── *.genesys-scene   - scene files (at the root of assets/, not in a scenes/ folder)
├── models/           - .glb files and associated .animconfig.json
├── materials/        - material assets (.material.json)
├── textures/         - texture images (.webp, .png)
├── sounds/           - audio files (.mp3, .wav)
├── UI/               - UI images, icons, fonts
├── VFX/              - visual effect sheets and animations
└── prefabs/          - reusable prefab definitions (.prefab.json)
```

Name assets descriptively and consistently. A texture called `T_GrassGround_Albedo.webp` tells you its type (texture), subject (grass ground), and map type (albedo). A file called `grassbumpmap.png` tells you less. The naming does not have to be elaborate, but it has to be consistent, because inconsistent asset names are the most common reason the AI pulls in the wrong file.

{% hint style="info" %}
*TIP: Use a prefix convention for asset types: `T_` for textures, `M_` for materials, `SM_` for static models, `SK_` for skeletal models, `SFX_` for sounds, and `UI_` for UI images. This is an industry convention that makes asset folders scannable at a glance and helps the AI identify the right asset type from a search.*
{% endhint %}

### **Editor organisation: naming what lives in the scene**

The scene editor is where your game world is assembled. Nodes placed in the scene should follow the same naming conventions as their classes. An instance of `HealthPickup` placed in the scene should be named `HealthPickup` or `HealthPickup_[purpose]` if multiple variants exist, not left as the default generated name.

Group related nodes in the scene hierarchy under labelled folders or parent nodes. A scene with a flat list of two hundred unnamed objects is one that neither you nor the AI can navigate efficiently. A scene with logical groupings (`Environment`, `Enemies`, `Spawnpoints`, `Triggers`, `Audio`) is one where finding anything takes seconds.

{% hint style="info" %}
*NOTE: Scene files (`.genesys-scene`) are managed by the editor and should not be opened or edited directly in code or in the AI context. Keep them out of your prompts. The editor handles them; your code handles the logic that runs inside them.*
{% endhint %}

### **Configuration and project-level files**

Keep project configuration at the root, not buried in subdirectories. Your `package.json`, `.gitignore`, and `<ProjectName>.genesys-project` file live at the root. Your `.cursor/` rules folder keeps Cursor's behaviour consistent across the project. Your `.agents/` folder holds the AI skill files that give Cursor context about the engine and your project conventions.

Do not create configuration files inside `src/`. Configuration belongs at the root level where it is immediately visible and where build tools expect to find it. Do not edit `src/auto-imports.ts` or `src/game-data.ts`.

## **Practical Guidance**

* Initialise Git before writing any code. Commit every verified feature as a checkpoint.
* Spend your time in `src/` and `assets/`. Leave generated files and `.engine/` alone.
* Group `src/` by what things are in the game (`Characters/`, `Gameplay/`, `Behaviours/`, `UI/`, `Core/`). Keep `game.ts` at the root of `src/`.
* Name scene node classes for the thing they are (`HealthPickup`). Register them with `@ENGINE.GameClass()`.
* Separate assets by type in `assets/`: `models/`, `materials/`, `textures/`, `sounds/`, `UI/`, `VFX/`, and `prefabs/`. Keep scene files (`.genesys-scene`) at the root of `assets/`.
* Use asset prefixes `T_`, `M_`, `SM_`, `SK_`, `SFX_`, and `UI_` as a team convention.
* Name scene objects in the editor the same way you name their classes. Leave no object with a default generated name.
* Group scene objects in the editor hierarchy by logical category: environment, enemies, spawnpoints, triggers, audio.
* Keep configuration at the project root. Nothing belongs in `src/` unless it is game logic, except the generated `auto-imports.ts` and `game-data.ts` files you never edit.
* When creating a new file, decide its folder and name before opening Cursor. Consistent structure means the AI always finds the right reference files without searching broadly.

## **Common Mistakes**

| Mistake                                                   | What to do instead                                                                                   |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Starting the project without Git                          | Initialise a repository first; committing after each working feature is your only reliable undo      |
| Naming files generically (`helper.ts`, `utils2.ts`)       | Name every file after what it specifically does; generic names make the codebase unsearchable        |
| Editing `auto-imports.ts` or using deprecated class names | Use `@ENGINE.GameClass()` on a `SceneNode`; never edit generated files                               |
| Leaving scene objects with default editor-generated names | Name every placed node in the scene to match its class name                                          |
| Storing all assets in a flat folder with no sub-structure | Separate by type from the start; reorganising assets mid-project is disruptive and breaks references |
| Committing broken or incomplete work                      | Commits are checkpoints; only commit a working state                                                 |
| Committing `.cursor/mcp.json` or rewriting `.gitignore`   | Leave the SDK ignore list in place; keep connection details off Git                                  |

Structure is not organisation for its own sake; it is the thing that keeps AI assistance accurate as the project grows. The AI finds the right file because it is in the right folder with the right name. The right commit is easy to return to because commits represent working states. The scene is navigable because objects are named and grouped. Set this up at the start and it maintains itself. Ignore it and every session gets slower as the project gets larger.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://studio-docs.sandbox.game/best-practices/project-structure.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
