> 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-code-fundamentals.md).

# Project code fundamentals

Game logic lives in TypeScript under `src/`. Follow this page when you add a custom node class and need it to appear in the editor. For how to name folders and assets, see [Project Structure](/best-practices/project-structure.md).

## Step 1: Put code in `src/`

Write your classes in `src/`. Keep `src/game.ts` as the entry point — it exports `main()` and returns the game loop. Do not move that file.

These files are generated on every `pnpm build`. Never edit them:

| Path                  | What it is                       | Editable?      |
| --------------------- | -------------------------------- | -------------- |
| `src/auto-imports.ts` | Registers your game classes      | **Never edit** |
| `src/game-data.ts`    | Editor metadata for your classes | **Never edit** |

`.engine/`, `.dist/`, and `.editor/` are also not yours to change. Folder layout for a growing project is on [Project Structure](/best-practices/project-structure.md).

{% hint style="info" %}
*NOTE: If a change disappears after a build, you edited a generated file. Put the code in your own file under `src/` instead.*
{% endhint %}

## Step 2: Register a SceneNode class

Everything you place in a scene is a `SceneNode`. Custom classes use `@ENGINE.GameClass()`. Never use `EngineClass` — that decorator is for the engine only.

`@ENGINE.property()` makes a field show in the Inspector and persist with the scene.

```typescript
import * as ENGINE from '@gnsx/genesys.js';

@ENGINE.GameClass()
export class HealthPickup extends ENGINE.SceneNode {
  @ENGINE.property({ /* editor-visible, serialized */ })
  healAmount = 25;
}
```

Player-controlled entities are **Pawns**, driven by **PlayerControllers**. Match rules live in a **GameMode**. Nodes with physics or collision are **PrimitiveNode**s. Meshes are **MeshNode** / **ModelMeshNode**. Do not name classes `*Actor` — v14 lint treats `Actor` as an error.

## Step 3: Run `pnpm build` then build in the editor

From the **project root** (the folder that contains `package.json`):

```
pnpm build
```

That command typechecks and regenerates `auto-imports.ts` and `game-data.ts`. It is the only build command you need in the terminal.

Then rebuild in Sandbox Studio so the new class registers for placing in the scene. Select `Build Project`, or press `Ctrl+B` / `Cmd+B`. The agent can run the same rebuild through the MCP build action.

To fix style in your TypeScript:

```
pnpm lint
```

`pnpm lint` runs ESLint with auto-fix. Do not use `pnpm dev`, `pnpm test`, or `pnpm start` — they are not supported workflows.

## Step 4: Use fully qualified asset paths

Always write the full path. Never concatenate or build paths in code.

* Project files: `@project/assets/...`
* Engine files: `@engine/assets/...`

Load a texture with the logical image extension (`.png` or `.jpg`) even if the build later compresses the file:

```typescript
ENGINE.resourceManager.loadTexture(
  ENGINE.AssetPath.fromString('@project/assets/textures/foo.png')
);
```

## Step 5: Reference classes in prefab and material JSON

In `.prefab.json` and `.material.json`:

* Engine types: `ENGINE.ClassName`
* Your `@ENGINE.GameClass()` types: `GAME.ClassName`

Prefer the editor (or the agent in the editor) for those files. Materials are editor-only. Prefabs can be hand-edited, but class names must match that `ENGINE.` / `GAME.` split. See [How to Set Up a Prefab](/the-editor/how-to-set-up-a-prefab.md). What JSON assets are in general: [What JSON files are in Sandbox Studio](/the-editor/what-json-files-are.md).

## Step 6: Keep generated files and scenes out of prompts

Do not:

* Edit `src/auto-imports.ts` or `src/game-data.ts`
* Use `EngineClass` on your types
* Ask the AI to open or edit `.genesys-scene` files — the editor owns those; keep them out of the agent context

## What You've Done

You can add a `SceneNode` with `@ENGINE.GameClass()`, run `pnpm build`, then select `Build Project` (`Ctrl+B` / `Cmd+B`) so the class shows up for placing. Step-by-step Place panel and prefab: [How to register a placeable GameClass](/the-editor/how-to-register-a-placeable-game-class.md). Save the project with `Ctrl+S` / `Cmd+S` before you upload or switch machines — [How to Save Your Project](/the-editor/how-to-save-your-project.md).


---

# 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-code-fundamentals.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.
