# Start Contributing to Babylon.js

> Learn how to start contributing to Babylon.js.

Source: https://doc.babylonjs.com/contribute/toBabylon/HowToContribute

## Introduction

Babylon.js is maintained on GitHub, a web-based hosting service for version control using Git. This page introduces GitHub and everything needed to make changes or additions to Babylon.js, from tool installation to testing, along with a brief description of why these steps are necessary. The steps are intended to be OS-agnostic, allowing users to develop the same way on Windows, Mac, and Linux.

## Pre-Requisites

- Reading the [contribution guidelines](https://github.com/BabylonJS/Babylon.js/blob/master/contributing.md).
- An ability to code in TypeScript. Babylon.js is written in TypeScript and then compiled and distributed in JavaScript.
- Know how to use a Command Line Interpreter (CLI), used to issue Git commands.

## Install Git

A quick option for Windows and Mac is the [Git Home Page](https://git-scm.com/), and for all three operating systems, the [Git Book](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).

You then need to configure the installation with your details using a CLI. You can use the CLI built into your computer or one of the many specialized ones for Git [(Git Clients)](https://git-scm.com/downloads/guis/). If you use Visual Studio Code, the Terminal is a built-in CLI and can be opened with `Ctrl +'` or `Terminal > New Terminal` on the menu.

In your CLI configure git globally with your user name and email:

```bash
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
```

## Fork from GitHub

If you do not already have one, open a GitHub account with your email address, sign in, and go to the [Babylon.js repository](https://github.com/BabylonJS/Babylon.js) to fork it using the top button.

![Fork](https://doc.babylonjs.com/img/contribute/fork.webp);

## Clone to Local

Now, in your **forked** Babylon.js repository, use the "Clone or Download" button to find **your** repository address:

![Clone](https://doc.babylonjs.com/img/contribute/clone.webp)

If the CLI you are using accepts pasting, use the copy icon to the right of the address. This will save a lot of typing. If not, enter this in the CLI:

```bash
git clone _**your repository address**_
```

![gitclone](https://doc.babylonjs.com/img/contribute/gitclone.webp)

The cloning may take some time.

Now you have a local repository and a remote repository on GitHub.

From the folder where you cloned Babylon.js into you can simply change your directory to the local repository using:

```bash
cd Babylon.js
```

and then find the name of your remote repository with:

```bash
git remote -v
```

![remote address](https://doc.babylonjs.com/img/contribute/remote1.webp)

You should find that it is called `origin` because it is the source of the cloned local version. The local branch is called `master` because it is your primary Babylon.js branch.
When the time comes, this will allow you to push changes from your local repository to your GitHub repository using:

```bash
git push origin master
```

## Keeping The Local Version Up To Date

When it comes time to request that your changes be pulled into the main Babylon.js repository, the only differences between your version and the main one should be the changes you made. Of course, other people are making changes as well, so you need to keep your local `master` up to date with the main version. The main version, often called the upstream version, is another remote that your local repository can link to.

To do this, add the main version as a remote named upstream, making sure your CLI is in the Babylon.js directory:

```bash
git remote add upstream https://github.com/BabylonJS/Babylon.js.git
```

Using

```bash
git remote -v
```

you can check that all remotes are active.

![Added Remote](https://doc.babylonjs.com/img/contribute/remote2.webp)

Now before pushing your fully committed master to your origin you can pull the upstream (main) version into your master with

```bash
git pull upstream master
```

You can pull from upstream at any time provided any changes you have made are committed.

## Editing and Building

Before embarking on editing or adding to Babylon.js please make sure you are familiar with the [contribution guidelines](https://github.com/BabylonJS/Babylon.js/blob/master/contributing.md).

Please note that some of these are checked on submission automatically by software, including

- The addition of comments to your code as described in [Contribute to the API](https://doc.babylonjs.com/contribute/toBabylon/contributeToAPI);
- Consistent coding style (linting).

### Editing with Visual Studio Code

Visual Studio Code is a straightforward IDE with Git integration and is available for all three operating systems. It is worth a try, even though you may already have a favorite or recommended IDE.

You can install VSCode from their site: [https://code.visualstudio.com/](https://code.visualstudio.com/)

[More on using VSCode with Babylon.js](https://doc.babylonjs.com/setup/support/vsCode)

### VSCode Extensions

If you are using VSCode, the repository comes with a list of recommended extensions. If you want to be able to debug entirely in VSCode you will need to install those extensions.

### Adding files

When in doubt about where your files should be added then raise an issue in the Babylon.js repository or ask on the forum.

### Commit

This can be done in Visual Studio Code using the _source control icon_ on the left toolbar or with (Ctrl + Shift + G). After testing, some files other than those you have added or edited will appear in the source control section of VSCode. These should not be committed. Once you are ready to push to your repository these changes should be discarded. Only files you have actually changed or added should be in the commit.

![Discard](https://doc.babylonjs.com/img/contribute/discard.webp)

When using a Git Client you should also check that you are _only committing those files you have added or edited_ and not those produced in any testing build.

When using a CLI, you need to add any files you have added or edited before committing them. So _only add those files you have changed_. The full path to the files from the current directory has to be used.

For example in the top directory

```bash
git add path to file/file1.ts path to file/file2.ts path to file/file3.ts
git commit path to file/file1.ts path to file/file2.ts path to file/file3.ts -m "Description of Changes"
```

![Commit top Folder](https://doc.babylonjs.com/img/contribute/commit1.webp)

and in the directory containing file1.ts, file2.ts, file3.ts

```bash
git add file1.ts file2.ts file3.ts
git commit file1.ts file2.ts file3.ts -m "Description of Changes"
```

![Commit in Folder](https://doc.babylonjs.com/img/contribute/commit2.webp)

### Install Node.js and NPM

Node.js and npm can be installed from the [Node.js home page](https://nodejs.org/en/).

Babylon.js currently requires Node.js `>=20.11.0 <23.0.0` and npm `>=8.0.0`.

To check your npm and node versions after Node.js is installed:

```shell
npm --version
node --version
```

### The Build

Run `npm install` in the main directory. This will install everything needed to get started with the repository.

It is recommended to run `npm run build:dev` before starting to work to make sure everything is in the right place.

Using VSCode? Install the recommended extensions and start `Run and Watch Dev Host (Dev)` to compile and get started with the esm dev host. To use the classic UMD-based development (and have the BABYLON namespace available), run `CDN Serve and watch (Dev)`.

To build the dev sources, shaders, and assets, run `npm run build:dev`.

To start the dev host, run `npm run serve -w @tools/dev-host`. This will start the dev host in [http://localhost:1338](http://localhost:1338) and will run the code located in the dev-host's src folder.

Note that this will not start watching the sources in the dev folder and will only watch for changes in the dev host src folder.

To start watching the dev packages, run `npm run watch:dev` in a new terminal window. This will make sure to watch all changes in the dev packages, including changes to shaders and assets, like scss files, images, and so on.

Following is a list of quick ways to get started with certain tasks, both in VSCode and command line. A quick way of finding a VSCode task: Ctrl+P (or Command+P on Mac), type "task", press the space button, and select the task you want to run.

#### Run the Babylon server

Using VSCode:

- Run "Run and watch Dev Server" from the Run and Debug Menu, OR
- Open the Command Palette, type "Run Task", select "CDN Serve and watch (Dev)"

Using command line:

- run `npm run watch:dev` (If you want to make changes to the dev packages. Otherwise run `npm run build:dev`)
- run `npm run serve -w @tools/babylon-server` in a new terminal window

The Babylon server offers 2 variants - js and ts. To load the js version (the default one) navigate to [http://localhost:1337](http://localhost:1337). To use the TS version navigate to [http://localhost:1337/index-ts.html](http://localhost:1337/index-ts.html).
The files to edit are sceneJs.js and sceneTs.ts in the source folder of the Babylon server package.

As described in the next section, the Babylon server also offers playground-snippet debugging.

#### Debug a playground snippet

To debug a snippet, run the localhost:1338 server in debug mode and add the snippet to the index. For example:

[http://localhost:1338#IQN716#9](http://localhost:1338#IQN716#9)

If you started the server in VSCode you will be able to debug the code straight in your IDE.

Note that the loader will react to changes in the hash (and will reload the scene), but will not save new data. To do that, run the playground itself.

#### Run the dev host

Using VSCode:

- Run "Run and watch dev host (Dev)" from the Run and Debug Menu, OR
- Open the Command Palette, type "Run Task", select "Run and watch Dev Host (Dev)"

Using command line:

- run `npm run watch:dev` (If you want to make changes to the dev packages. Otherwise run `npm run build:dev`)
- run `npm run serve -w @tools/dev-host` in a new terminal window

Open [http://localhost:1338](http://localhost:1338) in your browser.

#### Run the playground

Using VS Code:

- In the Run and Debug Menu, choose "Launch Playground" (Or "Playground development", in case you are making changes to the Playground code itself), OR
- Open the Command Palette, type "Run Task", select "Playground Serve for core (Dev)" (Or if you are just developing the playground itself, select "Playground Serve (Dev)")

Using command line:

- run `npm run watch:dev` (If you want to make changes to the dev packages. Otherwise run `npm run build:dev`)
- Run `npm run serve -w @tools/babylon-server` in a new terminal window
- Run `npm run serve -w @tools/playground` in a new terminal window

Shortcuts?

- Run `npx build-tools --command dev-watch --watch-assets --watch-declarations --serve` (watch and serve in one command)
- Run `npm run serve -w @tools/playground` in a new terminal window

Open [http://localhost:1338](http://localhost:1338) in your browser.

#### Run the sandbox

Using VS Code:

- In the Run and Debug Menu, choose "Launch Sandbox" (Or "Sandbox development", in case you are making changes to the Sandbox code itself), OR
- Open the Command Palette, type "Run Task", select "Sandbox Serve for core (Dev)" (Or if you are just developing the sandbox itself, select "Sandbox Serve (Dev)")

Using command line:

- run `npm run watch:dev` (If you want to make changes to the dev packages. Otherwise run `npm run build:dev`)
- Run `npm run serve -w @tools/babylon-server` in a new terminal window
- Run `npm run serve -w @tools/sandbox` in a new terminal window

Shortcuts?

- Run `npx build-tools --command dev-watch --watch-assets --watch-declarations --serve` (watch and serve in one command)
- Run `npm run serve -w @tools/sandbox` in a new terminal window

Open [http://localhost:1339](http://localhost:1339) in your browser.

#### Run the GUI editor

Using VS Code:

- In the Run and Debug Menu, choose "Launch GUI Editor" (Or "GUI Editor development", in case you are making changes to the GUI Editor code itself), OR
- Open the Command Palette, type "Run Task", select "GUI Editor Serve for core (Dev)" (Or if you are just developing the GUI Editor itself, select "GUI Editor Serve (Dev)")

Using command line:

- run `npm run watch:dev` (If you want to make changes to the dev packages. Otherwise run `npm run build:dev`)
- Run `npm run serve -w @tools/babylon-server` in a new terminal window
- Run `npm run serve -w @tools/gui-editor` in a new terminal window

Shortcuts?

- Run `npx build-tools --command dev-watch --watch-assets --watch-declarations --serve` (watch and serve in one command)
- Run `npm run serve -w @tools/gui-editor` in a new terminal window

Open [http://localhost:1341](http://localhost:1341) in your browser.

#### Run the Smart Filter Editor

Using VS Code, either:

- In the Run and Debug Menu, choose "Smart Filter Editor development" and click "Start Debugging (F5)"
- Open the Command Palette, type "Run Task", select "Smart Filter Editor Serve"

Using command line:

- Run `npm run watch:assets:smart-filters` in a terminal
- Run `npm run watch:source:smart-filters` in another terminal
- Run `npm run serve -w @tools/smart-filters-editor` in a third terminal

Open [http://localhost:1346](http://localhost:1346) in your browser.

#### Run tests

Using VSCode:

- In the Run and Debug Menu, choose "Run and Debug unit tests (Dev)" for the Vitest unit suite, or one of the validation test launch configurations for Playwright-based browser tests.
- Open the Command Palette, type "Run Task", and select "Run visualization tests (Dev)" or "Launch visualization test runner (Dev)".

Using command line:

- Run `npm run test:unit` or `npm run test:visualization`
- Run `npm run test` to execute the default root unit-test run

#### Link a public project to an external one

The example is linking `core`. Change the package name to anything else if needed.

- Build the public package you want to link:
  - `npx nx run babylonjs:build` (or es6 - `npx nx run @babylonjs/core:build`)
- Run `npm link -w [PACKAGE-NAME]` - for example `npm link -w @babylonjs/core`

In your other project:

- Make sure you are linking to the right version (or use semver ranges)
- Run `npm link [PACKAGE-NAME]` - for example `npm link @babylonjs/core`

When making changes to the linked package, make sure to repeat the build steps. There is no need to link again until you reinstall the public library.

Notes:

- This process will be simplified soon.
- You can link any package, not only the public one. However, you cannot rename the package. so if you link @dev/core you will need to add @dev/core to the dependencies of the external project.

#### Add a dependency to a project

Run `npm install packageName -w @namespace/package` (add -D to define a dev-dependency)

The package.json of the project should be changed.

Note: there is a bug in npm that, in certain cases, installs the dependency but doesn't add it to the package.json file. Run the command twice if that happens.

### Edit Code

Once the test task (`npm run start`) has been launched, any saved changes in the TypeScript or shader files will automatically rebuild the associated JavaScript files. Simply refresh your browser to see the changes take effect and begin debugging your new code.

_Hint_: You may need to refresh the code before adding back a new breakpoint.

## Repository structure

The repository is a monorepo. Every package has its own package.json and can be used independently, taking its dependencies into account.

Packages under `packages/dev` can be compiled together using the root TypeScript build, and dependent packages will be rebuilt automatically when needed.

Most packages share the same basic structure:

- src folder holds typescript files and assets
- test folder holds tests (See [Testing](#testing))
- dist folder holds compiled files, including sourcemaps and declarations, and assets (if configured)
- optional public folder for public assets that will be hosted when the package is served (only where applicable)

The build/watch/test scripts will take this structure into account.

All references during development are to the `src` folder of the packages, but all references during builds are to the `dist` folders. That means that, in order to compile a package, its dependents need to be compiled already. This is mainly handled by the build process and the watchers.

Dependencies are hoisted to the main directory, so the repository only has a single package lock file and a single node_modules directory.

NPM workspaces mean that you can execute any npm command on the entire repository, on a specific package, or on the root package.

To run a specific npm command on the entire repository, run `npm <command> -ws`.

To run a specific npm command on a specific package, run `npm <command> -w <package>`.

To run a specific npm command on the root package, run `npm <command>`.

Read more about node workspaces - [https://docs.npmjs.com/cli/using-npm/workspaces](https://docs.npmjs.com/cli/using-npm/workspaces)

### Naming convention

- npm packages are always lowercase kebab-case (i.e. gui-editor)
- directories are in camel case (i.e. guiEditor)

### Types of packages

There are 3 different types of packages:

#### dev packages

Packages with their name starting with `@dev`. These are the main packages that will be used on day-to-day work with the repository.
Those packages will hold raw assets in their dist directory, and are ready to be consumed by any packer (like webpack or rollup).

#### Tools packages

Packages with their name starting with `@tools`. Those packages hold tools that use the main repository.
Tools are, for example, the playground, the sandbox, node and GUI editor.

#### Public packages

The public-facing packages live under `packages/public`. They are the packages published to npm and are the only ones not marked `private` in their package.json.

### Running scripts

To run a script in a package, you can either run `npm run scriptname` in the package directory or `npm run scriptname -w @namespace/package-name` in the main directory. This is the recommended way of working.

For example, to build the dev core library you will run:

```shell
npm run build -w @dev/core
```

In the main directory.

If a script is missing from the package.json, you can either add it (not forgetting to commit the change) or run the script in the package directory using `npx`. For example, to use the installed TypeScript (and not the globally installed one), you can run:

```shell
npx tsc ....
```

In the specific project's directory.

The following scripts should be available for most if not all packages:

- build
- compile
- clean
- test
- format
- lint
- watch (serve on tools)

This is a work in progress. The scripts will be added to all packages. Please let @RaananW on the forums know if any script is missing from a specific package that you are trying to use.

### Initial source build and watch

To compile the dev code once in order to get the latest compiled code run:

```shell
npm run build:dev
```

To start a watcher that will watch the source code of the dev packages, run one of the following npm scripts:

```javascript
"format:check"; // check formatting,
"format:fix"; // fix formatting,
"lint:check"; // check linting,
"lint:fix"; // fix linting,
```

format:check and lint:check will run during CI once we have an issue-free repository.

### Dealing with assets

The dev and lts packages treat binary assets as files that will be part of their dist folder. When packing those assets, the packer can decide what to do with them (for example, by using url-loader or file-loader in webpack). The assets, which include binary media files and (s)css files, are watched and automatically copied/processed when the package is watched. To explicitly watch the assets in a specific project, run the build-tools "process assets" task (which will be fully documented later):

```shell
npx build-tools -c process-assets --isCore --watch
```

in the directory of the specific project. There should also be a `build:assets` and `watch:assets` script in the package.json of every package.

Shaders are also considered assets. They are processed differently, but they use the same script. Processing a shader (`.fx` file) will result in a TypeScript file, which will be compiled as part of the library during the build process. When building, `build:assets` will be executed before `compile:source`. The `build` script will take care of that for you. For example, `@dev/core` has the following scripts:

```javascript
"build": "npm run clean && npm run compile",
"precompile": "npm run compile:assets",
"compile": "npm run compile:source",
"compile:source": "tsc -b tsconfig.build.json",
"compile:assets": "build-tools -c process-assets --isCore",
```

### Formatting and lint

We have a global eslint and prettier configuration in the root of the repository. This unifies code structure and formatting throughout the repository. It is running on both .js and .tsx files.

When using VSCode, it is recommended to use both the Prettier formatter [extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) and the ESLint host in order to lint in real time.

To run the linter using the command line, run:

```shell
npm run lint
```

### Configuration options

Most packages in the repository don't need any extra configuration to compile. However, in certain cases you may want to control the way the files are compiled and served. A good example is enabling HTTPS support or changing the standard port used for the Babylon server or the tools.

There are a few options to pass configuration to the different packages.

#### Command line arguments

Both the build tools (explained later) and webpack (which is used to serve our tools) accept command line arguments. The following will be examples, but not full documentation of the different options and commands. The full list of options can be found further down the page.

When running the dev watcher, you can specify which packages will be watched. Using the standard way of starting dev watching (`npm run watch:dev`), you can do one of two things to add packages to the watcher:

```shell
# option 1, extend the npm run watch:dev command
npm run watch:dev -- --packages core,gui
# option 2, run the dev watcher directly (watching sources and assets)
npx build-tools --command dev-watch --watch-assets --packages core,gui
```

The same goes when running the serve command manually. For example, to enable production mode of the Babylon server:

```shell
# option 1, use the npm run command
npm run serve -w @tools/babylon-server -- --env=mode=production
# option 2 - use webpack directly in the Babylon server package directory
npx webpack serve --env=mode=production
```

In this specific case you have the task `npm run serve:prod` as well.

#### Using a .env file

When running both the playground and the Babylon server you have two servers running locally. The playground is being served, and the CDN is served on a different address. If we want to configure both of the servers at the same time, we can use a .env file to extend the command line arguments.

To use a .env file create a file called `.env` in the base directory of the repository. This file will be used automatically.

Think about the .env file as a way to extend `process.env`. The first important thing we need to know is that it will only be available during build time, but not in compiled code. So parameters set there are available in building scripts and in the build tools, but not in a `.tsx` file in the playground source directory. The variables are available globally.

To set a command line argument using the .env file, convert the parameter's name to upper case, and replace all `-` with `_`. For example, to set the packages from the example above, add this line to the .env file:

```shell
PACKAGES="core,gui"
```

To always watch assets when running the dev watch you can set the following in your .env file:

```shell
WATCH_ASSETS=true
```

To enable hot reload (another option existing in the webpack-enabled packages), add this line to the .env file:

```shell
ENABLE_HOT_RELOAD=true
ENABLE_LIVE_RELOAD=true
```

To set all (webpack) builds to production mode, set the following in the .env file:

```shell
NODE_ENV=production
```

Other optional variables you can set in the .env file are:

```shell
TOOLS_PORT=1338 # port for tools like the playground or the node editor
CDN_PORT=1337 # port for the Babylon server
CDN_BASE_URL="https://cdn.babylonjs.com" # base URL for the CDN. Defaults to localhost:1337. Useful if you want to test against a snapshot or the stable nightly
ENABLE_HTTPS=true # enable HTTPS for the Babylon server. Useful for WebXR
ENABLE_DEV_OVERLAY=true # shows the react dev overlay
```

Note that the .env file should never be updated on the repository. It is ignored by git.

To get the list of all the available options in each command, find it in this documentation page.

### Project linking

Projects' dependencies are defined in their package.json. However, when using dev or lts packages you can use a direct reference to the files instead of using the npm package itself. That means that you can (and should!) import directly from the needed library using its basic development package name. For example, these are the imports in the inspector (advancedDynamicTextureTreeItemComponent.tsx):

```javascript
// load from core
import { Nullable } from "core/types";
import { Observer, Observable } from "core/Misc/observable";
import { IExplorerExtensibilityGroup } from "core/Debug/debugLayer";

// load from gui
import { Control } from "gui/2D/controls/control";
import { AdvancedDynamicTexture } from "gui/2D/advancedDynamicTexture";
```

Using the dev package names (defined in the build tools) keeps local development pointed at the monorepo sources instead of published packages.

### Serving the repository

There are two basic ways to use the dev code:

#### Dev Host

The dev host allows you to write code using TypeScript or JavaScript, pack it with webpack, and serve it in your browser. The only file that should not be renamed is index.ts, which is the main entry file.

The dev host is similar to the ES6 packages we offer—everything must be imported, and no BABYLON namespace is available. If you want to test a playground scene, see the [Babylon server](#babylon-server) section below.

To run the dev host you execute the following command:

```shell
npm run serve -w @tools/dev-host
```

This will start watching the dev-host src folder and will run the code in the dev-host's src folder.

When loading from the different packages in the dev host you will use the package from which you are loading. For example, if you load the scene object from the dev core package, you will use:

```javascript
import { Scene } from "@dev/core";
```

It is important to stay consistent when importing, i.e. not to mix published `@babylonjs/*` packages with local `@dev/*` packages for the same code path, as TypeScript will treat them as different copies.

The dev host is configured to be much more forgiving when developing. The best example is the `noImplicitAny` rule, which is set to false. This is done mainly so you can load .js files as well as TypeScript files. This is the reason the `allowJs` flag is set to true.

The current simple structure of the dev host allows you to copy code from the playground and make the changes needed to run it in the dev host. For example, this playground:

```javascript
const createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  const scene = new BABYLON.Scene(engine);

  // This creates and positions a free camera (non-mesh)
  const camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);

  // This targets the camera to scene origin
  camera.setTarget(BABYLON.Vector3.Zero());

  // This attaches the camera to the canvas
  camera.attachControl(canvas, true);

  // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
  const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

  // Default intensity is 1. Let's dim the light a small amount
  light.intensity = 0.7;

  // Our built-in 'sphere' shape.
  const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2, segments: 32 }, scene);

  // Move the sphere upward 1/2 its height
  sphere.position.y = 1;

  // Our built-in 'ground' shape.
  const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene);

  return scene;
};
```

translates to this:

```javascript
import { canvas, engine } from "./index";
import { FreeCamera, HemisphericLight, MeshBuilder, Scene, Vector3 } from "@dev/core";

export const createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  const scene = new Scene(engine);

  // This creates and positions a free camera (non-mesh)
  const camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);

  // This targets the camera to scene origin
  camera.setTarget(Vector3.Zero());

  // This attaches the camera to the canvas
  camera.attachControl(canvas, true);

  // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
  const light = new HemisphericLight("light", new Vector3(0, 1, 0), scene);

  // Default intensity is 1. Let's dim the light a small amount
  light.intensity = 0.7;

  // Our built-in 'sphere' shape.
  const sphere = MeshBuilder.CreateSphere("sphere", { diameter: 2, segments: 32 }, scene);

  // Move the sphere upward 1/2 its height
  sphere.position.y = 1;

  // Our built-in 'ground' shape.
  MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene);

  return scene;
};
```

A simpler way to do that would be to load the entire @dev/core package as BABYLON:

```javascript
import { canvas, engine } from "./index";
import * as BABYLON from "@dev/core";

export const createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  const scene = new BABYLON.Scene(engine);

  // This creates and positions a free camera (non-mesh)
  const camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);

  // This targets the camera to scene origin
  camera.setTarget(BABYLON.Vector3.Zero());

  // This attaches the camera to the canvas
  camera.attachControl(canvas, true);

  // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
  const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

  // Default intensity is 1. Let's dim the light a small amount
  light.intensity = 0.7;

  // Our built-in 'sphere' shape.
  const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2, segments: 32 }, scene);

  // Move the sphere upward 1/2 its height
  sphere.position.y = 1;

  // Our built-in 'ground' shape.
  BABYLON.MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene);

  return scene;
};
```

The catch here is that this is not the actual BABYLON namespace, this is just the core namespace and will not include the loaders, for example, even if imported.

This is an extended example of how to use the dev host to integrate GUI, Loaders and the inspector:

```javascript
import { canvas, engine } from "./index";
import "@dev/loaders";
import { Inspector } from "@dev/inspector";
import { ArcRotateCamera, CubeTexture, Scene, AppendSceneAsync } from "@dev/core";
import { AdvancedDynamicTexture, Button } from "@dev/gui";

export const createScene = async function () {
    const scene = new Scene(engine);
    scene.createDefaultCameraOrLight(true);
    const hdrTexture = new CubeTexture("https://playground.babylonjs.com/textures/SpecularHDR.dds", scene);
    scene.createDefaultSkybox(hdrTexture, true, 10000);

    // The first parameter can be used to specify which mesh to import. Here we import all meshes
    AppendSceneAsync("https://assets.babylonjs.com/meshes/webp/webp.gltf", scene).then((result) => {
        scene.activeCamera!.attachControl(canvas, false);
        // scene.activeCamera!.alpha += Math.PI; // camera +180°
        (scene.activeCamera as ArcRotateCamera).radius = 80;
    });

    const advancedTexture = AdvancedDynamicTexture.CreateFullscreenUI("UI");

    const button1 = Button.CreateSimpleButton("but1", "Click Me");
    button1.width = "150px"
    button1.height = "40px";
    button1.color = "white";
    button1.cornerRadius = 20;
    button1.background = "green";
    button1.onPointerUpObservable.add(function() {
        alert("you did it!");
    });
    advancedTexture.addControl(button1);

    Inspector.Show(scene, {});

    return scene;
};

```

The dev host is configured with hot reload and live reload, making sure that if you change any file in the dev host source directory, the dev host will update (or reload) the page. However, it will not react to changes to the source code in the dev packages, as it is using the compiled version of the dev packages.

If you want to watch the source code of the dev packages, you will need to start the watcher manually or use the configured VSCode tasks (more on that later). Using VSCode is recommended, but not required.

To compile the dev code once in order to get the latest code in the dev host see "Initial source build and watch".

Note about the dev host: it does not use best practices for production code. It is a tool for developing with the dev packages and is not meant to be used in production.

#### Babylon Server

The Babylon server is a direct copy of the Babylon CDN structure. It serves JavaScript files, along with sourcemaps and declarations.

Similar to the dev host, the Babylon server will take the latest compiled code from the current monorepo packages and serve it to the browser. The default address for the local CDN is [http://localhost:1337](http://localhost:1337).

The Babylon server's _index.html_ has references to all of our public packages and has the BABYLON namespace populated, similar to how the playground works. If you want to debug a playground scene without starting the playground, edit the files `sceneJs.js` or `sceneTs.ts` in the babylon-server package and open [http://localhost:1337/index.html](http://localhost:1337/index.html) or [http://localhost:1337/index-ts.html](http://localhost:1337/index-ts.html).

To start the Babylon server, run:

```shell
npm run serve -w @tools/babylon-server
```

This will start a new server on port 1337 and will host all the needed files, including a very simple _index.html_ file to make sure the CDN is working.

The babylon-server package also serves all other files needed for tools like the playground to work correctly. It hosts the physics engine, earcut, the draco decoder, and more. See the `public` directory in the babylon-server package to see what files are available. Those files are served as static files.

As with the dev host, if you want to watch the source code of other packages, you will need to run the watcher/compile manually or use the configured VS Code tasks (more on that later). Using VSCode is recommended, but not required. See "Initial source build and watch" for dev code compilation and watch.

The Babylon server can be used wherever the compiled packages are needed, like the playground.

In order to use the Babylon server, run the Babylon server (`npm run serve -w @tools/babylon-server`), and start the playground in a different terminal. As always, there is a VS Code task and launch configuration for the playground.

A few notes:

1. Regarding performance - minified code loads faster (or at least SHOULD load faster). Meaning that running the server in production mode (using `npm run serve:prod -w @tools/babylon-server`) will help running code relying on the compiled packages faster. However, the actual build of the server will be roughly 2x slower than the dev build. If you want to use the server in order to work on tools like the GUI editor or the playground (working on and not with - i.e. editing those packages' code), it is recommended to run the Babylon server in production mode.
2. Regarding the packages created by babylon-server - The packages generated by the server are very similar to the public UMD packages, but they are not entirely the same. The babylon-server is not meant to be used in production! It is just a development tool.

As with any webpack-hosted package, there are a few properties that can be configured (using either the CLI or the .env file, as discussed above):

- mode: the type of build you will use. This can be either 'production' or 'development'. The default is 'development'.
- cdnPort: the port that the Babylon server will be hosted on. The default is 1337.
- enableHttps: whether or not to use https. The default is false.
- enableHotReload: whether or not to enable hot reload. The default is false. It is never enabled in production mode.
- enableLiveReload: whether or not to enable live reload. The default is false. It is never enabled in production mode.

## Tools

We have several tools that we are hosting for our users. All of them (playground, sandbox, node editor and the GUI editor) are using the same architecture when it comes to referencing the core library - they use our UMD packages (the files that are hosted on our CDN). This is why, in order to get them to work you need to make sure the Babylon server is running in the background. See [Babylon Server](#babylon-server) for more information.

All tools are packed and served with webpack, and are configured similarly.

To start the tools use the `serve` command:

```shell
npm run serve -w @tools/package-name
```

Most packages will work the same and are therefore not fully documented.

Notes:

- If the playground is served using HTTPS, the Babylon server must be HTTPS-Enabled as well.
- To load the dist files (and avoid using the babylon-server) add ?dist=true to the url.
- Local ports vary by tool. Use the relevant section above or the VS Code launch configuration for the exact URL.

### Playground

The playground is not a public package, but is served on [https://playground.babylonjs.com](https://playground.babylonjs.com). It is a tool for developers to test their code and see how it works.

In order for it to work during production you will need to have a running Babylon server or use the dist query parameter.

To start the playground:

```shell
npm run serve -w @tools/playground
```

There are VS Code tasks that will allow you to both start the playground for playground development and to start the dev package watcher to also watch the dev packages. The first option is meant for developers working on the playground package, and the other is meant for developers of dev packages that want to test them on the playground.

Notes:

- when importing files from core, reference the `@dev/core` package without setting the directory. The reason is that the class will eventually be loaded from the BABYLON namespace, available in the playground.
- It is probably quicker to test your changes in the dev host instead of the playground.

### Debugging

Every package at every stage can be fully debugged using either the browser (Chrome recommended) or the VS debugger.

To start the debugger using VS Code use the launch task you want to debug and run it. Note that it might take a little while for VS Code to initially load the files that it is debugging.

All packages are built with sourcemaps (when not in production mode), so opening the browser and choosing the file to debug will let you debug using TypeScript sources.

Unit tests can be debugged as well using the VS Code debugger. The built-in Vitest launch configurations run without file parallelism, which makes breakpoints predictable. Set the breakpoint beforehand and run the tests. The initial run might take some time, but once the debugger is connected it will stop at that breakpoint.

Contact us in the forum with any issues regarding debugging.

Until we fix all of the ESlint issues, make sure to press "Debug anyways" when running VS Code debugger tasks.

### Watchers

See build-tools dev watcher

### Adding a new package

To add a new package, follow the steps below:

- Choose the location of the package
- Add a new directory in the package category
- Add a package.json (you can copy a similar one from a different package). Make sure the package is marked "private" if it's not to be published.
- make sure you name your package correctly (i.e. @tools/package-name)
- Add your code using the schema described above (src for sources and assets, test for tests, etc.)

To install new dependencies to the package you can either add them to the package.json manually, or run `npm install package-to-install -w @namespace/package-name` in the package directory. Add `-D` to the command if you want to install dev dependencies.

Once this is done you can use this package in the workspace (using the `-w` argument when running npm commands).

You can reference this package in other packages to link them together. Once this is done (the package is added to the dependency list of another local package) it will be available in node_modules.

### Building

To build each and every package available in the repository, run `npm run build -w @namespace/package-name`. There is, however, a quicker and more efficient way of building a package that has dependencies.

`nx` is integrated into the repository and can be used as a local build orchestrator to run builds much faster. When running an npm script using nx, it will automatically run the same command in local dependencies and in the right order. For example, when building a public package such as `babylonjs-gui` using `npx nx run babylonjs-gui:build`, nx will add the required dependent projects to the sequence automatically.

It will run the build in sequence (because of the predefined dependencies), but will skip building a package if it hasn't changed since the last build call. So calling `npx nx run babylonjs:build` will build the projects needed for that target and reuse anything that is already up to date when another package depends on it.

This should be used only when you want to build the public packages in the repository, and it will mainly be used by the CI. However, nx is available to you and is a very powerful tool. In the future, we might integrate it more deeply into the repository. To read more about nx: [https://nx.dev/getting-started/intro](https://nx.dev/getting-started/intro)

## Testing

There are 3 types of tests configured in the repository:

- unit (Vitest)
- visualization (Playwright)
- integration (Playwright)

Each package can have a "test" folder with a specific structure. The structure of the test folder will allow tests to run automatically in the entire repository (and in a single package). The structure is as follows:

- unit tests are located in `test/unit`.

All files must follow this schema:

`(.*).test.{ts, tsx}`, for example - materials.test.ts

At the repository level, the Vitest `unit` project automatically picks up files matching `packages/**/test/unit/**/*.test.{ts,tsx}`.

The default unit-test environment is `node`. When a unit test needs DOM APIs, switch the file to `jsdom` by adding a comment at the first line of the file. For example:

```javascript
/**
 * @vitest-environment jsdom
 */
```

This enables jsdom for that file and makes `window` and `document` available in the test. Browser-based visualization and integration tests run separately through Playwright rather than through the Vitest unit project.

Test results can be seen on the console. In CI, Vitest also emits a `junit.xml` report for test reporting.

Visualization tests will generate a report if any test failed. The report will open automatically after running the tests.

To run the repository's unit-test suite from the root, run `npm run test` or `npm run test:unit` in the main directory.

We are testing unit suites using Vitest. To learn more about the test runner and its API, read the Vitest documentation - [https://vitest.dev/guide/](https://vitest.dev/guide/)

### Unit testing

Apart from what's written before, there are a few things that need to be observed when writing unit tests.

- Unit tests are meant to test a specific unit or module. Anything else should be mocked. To read more about Vitest mocking, see [https://vitest.dev/guide/mocking.html](https://vitest.dev/guide/mocking.html)
- If you are testing the connection between two or more modules it is not a unit test and should probably be an integration test.
- Do not use browser-based Playwright tests as a substitute for unit tests. If `node` is not enough, prefer `@vitest-environment jsdom` before moving to visualization or integration coverage.
- jsdom does not allow adding script tags to the DOM. Anything that needs to be added externally must be mocked.

To run all unit tests, run `npm run test:unit` from the repository root.

To run a specific unit test file, pass its path to Vitest from the repository root:

`npm run test:unit -- packages/dev/core/test/unit/Math/babylon.math.vector.test.ts`

To run tests matching part of the test name, use Vitest's `-t` filter:

`npm run test:unit -- -t "material"`

To debug the current test file from VS Code, use the "Run and Debug current unit test file (Dev)" launch configuration.

### Visualization tests

Before running the visualization tests, you'll need to start the local server:

```shell
npm start
```

Run all visualization tests (WebGL1, WebGL2 and WebGPU) using `npm run test:visualization` in the main directory.

#### Before your first test run

The tests are run using Playwright.
If you haven't already installed Playwright's browsers, please do so by running `npx playwright install`.

#### Running all tests

To run all visualization tests run `npm run test:visualization` in the main directory.

If you want to run only one specific engine, add the following:

```shell
npm run test:visualization -- --project="webgl2"
```

If any error occurs during the test, the tests will continue and will eventually generate a report with all the failed tests. The report will open automatically after the tests are done.
You can stop the execution and still see the report (if any tests failed) by pressing `Ctrl+C`.

#### Adding a new test

To add a new test to the visualization tests, add the test data to [packages/tools/tests/test/visualization/config.json](https://github.com/BabylonJS/Babylon.js/blob/master/packages/tools/tests/test/visualization/config.json)

The best way to do that is to first create a playground, save it (using a local version of the playground, for example), and then add it at the end of the config file:

```json
//...,
{
  "title": "My new visualization test", // the title of the test
  "playgroundId": "#ABCDEF#12", // the playground snippet id
  "referenceImage": "nameOfReferenceImage.png", // a name for the image snapshot that will be generated. Optional!
  "excludedEngines": ["webgl1"], // optional lists of engine you don't want the test to run on
  "renderCount": 2, // optional, the number of frames the scene should render. Default is 1. Good for animated scenes.
},
//...
```

To generate the snapshot, run the test once. The simplest would be to open the UI and run the test. The snapshot will be generated in the `tests/test/visualization/snapshots` folder. Make sure to add the snapshot to the repository. See the next section to know how to run a single test.

#### Running specific tests

The recommended way to run a specific test is to use the UI. To do that run

```shell
npm run test:visualization:ui
```

This will show you the tests for all 3 engines and you will be able to run them one by one.

If you want to display only one specific engine, add the following:

```shell
npm run test:visualization:ui -- --project="webgl2"
```

This will only show the tests for the webgl2 engine.

Note that when making changes to the list of tests the UI will reload to show it. So you can update the JSON while the UI is loaded without the need to run it again.

If you don't want to use the UI you can run an individual test by providing its title:

```shell
npm run test:visualization -- --project="webgl2" -g "Title Of The Test"
```

### Guidelines

A reminder to read the [contribution guidelines](https://github.com/BabylonJS/Babylon.js/blob/master/contributing.md).

## Pull-Request

Pull Requests are automatically validated with linting and testing.

When you are happy that all testing has been validated, the guidelines have been followed, and only the necessary files have been committed, then push your local master to your origin GitHub repository with your Git client or from the CLI with:

```bash
git push origin master
```

Once this has succeeded, visit your Babylon.js repository. If all your commits are ahead of the upstream Babylon.js:master, you can issue a pull request using the Contribute button shown below and follow the steps:

![Success](https://doc.babylonjs.com/img/contribute/pr1.webp)

If some of your commits are behind the upstream Babylon.js:master, then you will need to run:

```bash
git pull upstream master
```

and then push into your repository again.

## Check for Success

Once your `pull-request` has been issued, it needs to be checked, reviewed, approved, and merged. Find your pull-request in the list and open it:

![check 1](https://doc.babylonjs.com/img/contribute/pr3.webp)

Scroll down to the review panel. If there are any failures, a red cross indicates the area of failure. Click on details for more information:

![check 1](https://doc.babylonjs.com/img/contribute/pr4.webp)

Then click on the link under "Build job failed" to be taken to an Azure Pipelines page where you can see the output of your build job and understand better why it failed:

![check 2](https://doc.babylonjs.com/img/contribute/pr5.webp)

![check 3](https://doc.babylonjs.com/img/contribute/pr6.webp)

For any failures re-edit your local files, commit and push to your repository. The alterations will be automatically added to your pull-request and it will be re-checked.

## It's Live

Once your pull-request has been merged, it will become live once the changes have been deployed into the `Preview Release`, usually overnight, though sometimes delayed by a couple of days.

## Summary

### App Install

Node.js and Git

### Fork and Clone

![Fork and Clone](https://doc.babylonjs.com/img/contribute/summary1.webp)

### Name Remotes and Pull

![Remotes](https://doc.babylonjs.com/img/contribute/summary2.webp)

### Local Install

```bash
npm install
```

### Local Build and Serve

Using VSCode? Install the recommended extensions and start `Run and Watch Dev Host (Dev)` to compile and get started with the esm dev host. To use the classic UMD-based development (and have the BABYLON namespace available), run `CDN Serve and watch (Dev)`.

To build the dev sources, shaders, and assets, run `npm run build:dev`.

To start the dev host, run `npm run serve -w @tools/dev-host`. This will start the dev host in [http://localhost:1338](http://localhost:1338) and will run the code located in the dev-host's src folder.

Note that this will not start watching the sources in the dev folder and will only watch for changes in the dev host src folder.

To start watching the dev packages, run `npm run watch:dev` in a new terminal window. This will make sure to watch all changes in the dev packages, including changes to shaders and assets, like scss files, images, and so on.

### Edit

Change and save files including comments.

### Test

Check if your code can be used in the local playground.

### Success

Commit files you have added or edited but not those built.

### Push Pull-Request Check

![Pull-Request](https://doc.babylonjs.com/img/contribute/summary3.webp)
