diff --git a/docs/_partials/defaultProjects.md b/docs/_partials/defaultProjects.md
new file mode 100644
index 000000000000..f4955771b40a
--- /dev/null
+++ b/docs/_partials/defaultProjects.md
@@ -0,0 +1,8 @@
+Ethereal Engine has a few scenes that are installed by default.
+With the engine running, open the Studio by navigating to https://localhost:3000/studio, and you will see the engine's default project listed in that page.
+
+Lets give them a test run:
+- Open one of the default project by clicking on its card
+- Click on one of the scenes to open it
+- Click on the `Play` button to enter the scene with an Avatar
+- Move around the scene with `WASD` and/or clicking on the ground
diff --git a/docs/_partials/installUbuntu.md b/docs/_partials/installUbuntu.md
new file mode 100644
index 000000000000..d3ebebe7bc19
--- /dev/null
+++ b/docs/_partials/installUbuntu.md
@@ -0,0 +1,19 @@
+:::important
+Ethereal Engine is a web application.
+We are going to install and run a local version of the engine.
+But this setup might not reflect how you will use the engine on a day to day basis.
+:::
+
+:::note
+These installation instructions assume you are using Ubuntu Linux.
+You can find alternative _(and more advanced)_ installation instructions for [Windows](/manual/install/windowsWSL), [Mac](/manual/install/macOSX) and [Linux](/manual/install/linux) in the Manual.
+:::
+
+If you are on Ubuntu Linux, there is an automatic installation script to setup and run a local version of Ethereal Engine.
+Open a terminal window and run these two lines:
+> Make sure that you open the terminal in the folder where you want to install the engine
+```bash
+wget https://raw.githubusercontent.com/EtherealEngine/etherealengine/dev/scripts/ubuntu-install.sh && bash -i ./ubuntu-install.sh
+npm run reinit && npm run dev
+```
+You can now open Ethereal Engine on your web browser by navigating to https://localhost:3000
diff --git a/docs/developer/typescript/01_gettingStarted/01_file.md b/docs/developer/typescript/01_gettingStarted/01_file.md
deleted file mode 100644
index 7db4cab12c85..000000000000
--- a/docs/developer/typescript/01_gettingStarted/01_file.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/01_gettingStarted/01_quickstart.md b/docs/developer/typescript/01_gettingStarted/01_quickstart.md
new file mode 100644
index 000000000000..fd844b846977
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/01_quickstart.md
@@ -0,0 +1,43 @@
+---
+sidebar_label: Quickstart
+---
+import UbuntuInstall from '../../../_partials/installUbuntu.md'
+import DefaultProjects from '../../../_partials/defaultProjects.md'
+
+# Typescript Quickstart
+This QuickStart guide will teach you the basics of Ethereal Engine, and how to run the engine for the first time.
+
+## Installation
+
+
+## Projects
+### Default Projects
+
+
+### Install and Run the tutorial project
+Whether you installed the engine with method above, or with the installation instructions for your specific system, your next step will be to install the tutorial project.
+
+:::danger
+This `HelloWorld` project should never be installed in a remote deployment.
+A local version of the engine is required to follow this introductory tutorial.
+:::
+
+The previous commands will have the engine running locally.
+Lets stop it by pressing `Ctrl+C`, and then run these commands to install and run the tutorial's template project:
+```bash
+git clone -b Step0 https://github.com/EtherealEngine/ee-tutorial-hello packages/projects/projects/ee-tutorial-hello
+npm run dev
+```
+
+You should now be able to see the `ee-tutorial-hello` project listed in Ethereal Engine's Studio by navigating to https://localhost:3000/studio.
+
+## Confirm the installation
+Lets make sure that our `hello world` code is running:
+1. Open the project from the Studio by clicking on its card
+2. Create a new empty scene
+
+You will know that the code is running if you can see a white sphere in the middle of the scene.
+
+:::note
+You can also enter the scene and move around with an avatar by pressing the `Play` button in the editor like we did before.
+:::
diff --git a/docs/developer/typescript/01_gettingStarted/02_file2.md b/docs/developer/typescript/01_gettingStarted/02_file2.md
deleted file mode 100644
index 7db4cab12c85..000000000000
--- a/docs/developer/typescript/01_gettingStarted/02_file2.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/01_ecs.md b/docs/developer/typescript/01_gettingStarted/02_hello/01_ecs.md
new file mode 100644
index 000000000000..0cdb3a3a2a08
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/01_ecs.md
@@ -0,0 +1,87 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+
+# The ECS Pattern
+The [Entity Component System](https://en.wikipedia.org/wiki/Entity_component_system) is a pattern used to organize our code when writing software.
+In this pattern:
+- Logic is represented as `Systems`, and they define the behavior of the application
+- Data is represented as `Components` that have no behavior or identifiers attached to them
+- Components are attached to Entities
+- `Entities` are identifiers
+
+
+The ECS pattern represents [Objects](https://en.wikipedia.org/wiki/Object_(computer_science)) by attaching Components (data) to an Entity (identifiers) without behavior.
+The behavior of the application is then controlled by having separate Systems (logic) that process that data.
+Systems don't need to know where that data is coming from. They only know what data is stored in the Components that they can operate on.
+
+
+:::note
+Clicking on the `Technical Summary` note right above will open a drop-down with information about what the ECS pattern is in more advanced/technical terms.
+
+You will find a lot of these `Technical` drop-downs throughout the guides.
+Their goal is to give you extra information that is not mandatory to understand to follow the guide, but is very useful to achieve a deeper understanding of the content.
+
+Don't worry if you don't fully understand what some of them explain just yet. We will get there.
+:::
+
+## Creating an Entity
+Creating an Entity is as simple as calling the `createEntity()` function from Ethereal Engine's `ECS`.
+This function will return an identifier that can be used to group Components into a unique and distinct Object.
+```ts
+const entity = ECS.createEntity()
+```
+
+## Adding Components
+Components represent data that has no behavior or identification.
+The way to attach Components to Entities is by calling the `setComponent` function from Ethereal Engine's `ECS`.
+
+
+The `setComponent` function will not return anything, but it will:
+- Add the given Component to the Entity.
+- Store the Component's data in the internal records of the ECS, so it can used by the engine or accessed through the API _(eg: with `getComponent` and similar functions)_.
+
+
+Ethereal Engine requires a specific set of Components in order to create an object that can be presented on the screen:
+- **VisibleComponent**
+- **TransformComponent**
+- **PrimitiveGeometryComponent** or **MeshComponent**
+- _(optional)_ **NameComponent**: Not required, but good practice.
+
+
+### `NameComponent`
+Gives a human-readable identifier to an Entity.
+Whatever name you add on this field is the name that will show up in the Studio and the debugger.
+They are not mandatory, but it is good practice to add them to all your entities.
+```ts
+ECS.setComponent(entity, NameComponent, 'hello-world')
+```
+
+We said that an entity is an identifier, but we are also giving that identifier a `NameComponent`.
+Every Entity represents its internal "name" _(aka identifier)_ as an [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier), which does not need to be human-readable.
+And `NameComponents` give a human-readable identifier to an Entity, independent of what its UUID is.
+
+
+
+### `VisibleComponent`
+Gives the Entity the ability to be visible on the screen.
+Entities without this Component will be ignored by the renderer.
+```ts
+ECS.setComponent(entity, VisibleComponent)
+```
+
+### `TransformComponent`
+In simple terms, `TransformComponents` give an Entity the ability to have a [position in the world](https://en.wikipedia.org/wiki/Transformation_matrix).
+There would be no way to position the Entity in 3D space without attaching this Component to the Entity.
+```ts
+ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+```
+> In more technical terms, `TransformComponents` give the Entity the ability to be affected by [linear transformations](https://en.wikipedia.org/wiki/Linear_transformation).
+
+### `PrimitiveGeometryComponent`
+This Component gives Entities a primitive "visual body".
+Entities without it would not have any [3D geometry](https://en.wikipedia.org/wiki/Polygon_mesh), so the renderer would not be able to draw them on the screen.
+```ts
+ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: 1 })
+```
+> The `1` here means that we are creating a [`SphereGeometry`](https://github.com/EtherealEngine/etherealengine/blob/dev/packages/engine/src/scene/constants/GeometryTypeEnum.ts#L28) object.
+> We will create the component using a more readable name in the next section of the tutorial.
+
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/02_engine.md b/docs/developer/typescript/01_gettingStarted/02_hello/02_engine.md
new file mode 100644
index 000000000000..7a8a22ea9dda
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/02_engine.md
@@ -0,0 +1,205 @@
+---
+sidebar_label: The Engine
+---
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Working with Ethereal Engine
+You will need three very important steps for creating a project with Ethereal Engine:
+1. Installing Ethereal Engine
+2. Installing (or creating) a project
+3. Modify and run the source code of your project
+
+We already solved #1 and #2 in the [Quickstart](../quickstart) guide.
+Lets do a quick review of how #1 and #2 work, and we will start programming with the engine right after.
+
+## Requirements and Dependencies
+We will use `git` and `npm` a lot throughout the guides on this website.
+
+Whether you followed the Quickstart guide for Ubuntu, or installed the engine with the Manual instructions, you will have both `git` and `npm` already installed.
+
+You don't need to understand either of them to get started. This guide will teach you what to do every time they are needed.
+Just remember that they are used a lot to work with the engine locally.
+
+## Installing and running Ethereal Engine
+Ethereal Engine is a web application.
+Just like any other web application, it needs to be run in a server. And that server will provide access to the engine remotely to anyone with access to its address.
+
+We will eventually learn how to work with "deployed" versions of the engine.
+But we need to follow this tutorial in a `local development server` instead.
+
+That's exactly what the Quickstart installation guide automated for us.
+As the `localhost` part of the URL indicates, we are running a `local` version of the engine.
+
+## Installing and running projects
+Ethereal Engine can be **extended** with projects.
+They are equivalent to the concept of "projects" in other engines, except they are modular like npm packages _(they are npm packages too)_.
+
+The engine scans for projects mounted in the `/packages/projects/projects` sub-folder.
+This means that we can install and run new projects by executing the following commands inside our Ethereal Engine installation folder:
+```bash
+git clone https://github.com/EtherealEngine/ee-tutorial-hello packages/projects/projects/ee-tutorial-hello
+npm run dev
+```
+:::note
+You will need to stop the engine and re-run it whenever you install a new project.
+:::
+
+
+Please note that, in the [Quickstart](../quickstart) guide, we cloned the `Step0` branch from the `ee-tutorial-hello` project specifically, and not the whole project.
+We did this by adding `-b Step0` to the `git clone` command:
+
+```bash
+git clone -b Step0 https://github.com/EtherealEngine/ee-tutorial-hello packages/projects/projects/ee-tutorial-hello
+```
+
+This step won't be needed for your own projects.
+
+
+These steps will:
+- Download a copy of the project's git repository, so the engine can load it
+- Install all `npm` packages required by the project
+- Run a local development version of the engine
+
+:::note
+This is also the process recommended for installation of your own projects.
+The difference will be that, instead of starting your project from the minimal HelloWorld example like we are doing now, you will start from a pre-made template.
+:::
+
+:::important
+Each project's source code is executed globally.
+This will become very important later on in this guide.
+:::
+
+
+## Programming with Ethereal Engine
+There are two very important steps to take in order to connect the source code of our project to the engine:
+- We need to import some Ethereal Engine's modules
+- We need to export our code so the engine can run it
+
+### Project Configuration File
+Every project has an `xrengine.config.ts` file that defines how it will behave in the engine.
+There are multiple options available, but the important thing to remember is that our `src/Hello.ts` code will be connected to the engine from here.
+
+
+
+```ts title="ee-tutorial-hello/xrengine.config.ts"
+import type { ProjectConfigInterface } from '@etherealengine/projects/ProjectConfigInterface'
+
+const config: ProjectConfigInterface = {
+ onEvent: undefined,
+ thumbnail: '/static/etherealengine_thumbnail.jpg',
+ routes: {},
+ services: undefined,
+ databaseSeed: undefined,
+ // highlight-start
+ worldInjection: () => import('./src/Hello') // Import our Hello World code
+ // highlight-end
+}
+
+export default config
+```
+
+
+We don't need to know much more about this file for now. We will explore it further in the `Beyond the Basics` guide.
+
+### Module Imports
+In this minimal tutorial we are adding a sphere primitive to the scene.
+As this sphere will be a `Spatial` object, we will import a few components from the Spatial engine module:
+
+```ts title="ee-tutorial-hello/src/Hello.ts"
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+```
+We will be adding these Components to our Entity, and Components are part of the ECS pattern.
+As such, we will need to use the Ethereal Engine ECS management functions.
+The engine provides a convenient way to import all ECS related functions at once through the `ECS` [namespace](https://www.typescriptlang.org/docs/handbook/namespaces.html).
+```ts title="ee-tutorial-hello/src/Hello.ts"
+import { ECS } from '@etherealengine/ecs'
+```
+
+## Modifying our Source Code
+We have learned how our minimal example works, but so far we haven't needed to modify any of its source code.
+This will be our first modification to the code of the project.
+
+:::important
+This guide uses [`Project-based Learning`](https://en.wikipedia.org/wiki/Project-based_learning) as its core teaching philosophy.
+From now on, you will be actively modifying the source code of the `ee-tutorial-hello` in every step of the way.
+:::
+
+Lets start with a simple change.
+We will modify our Sphere `PrimitiveGeometryComponent` to load our geometry with a name, instead of the hardcoded number `1` that we used before.
+
+In order to do this, we need to:
+- Open the file `ee-tutorial-hello/src/Hello.ts` with a text editor.
+- Import the `GeometryTypeEnum` from the `scene/constants/` sub-module inside the `engine` module.
+- Replace the `1` with a call to the `SphereGeometry` name that is stored inside it `GeometryTypeEnum`.
+
+Try to figure out the changes by yourself before looking at the solution.
+I don't expect you to know where that enum is stored, so here are some hints to make it easier:
+```ts
+// The full path to the GeometryTypeEnum is:
+'@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+
+// Getting the ID number of a Sphere by its enum name will look like:
+GeometryTypeEnum.SphereGeometry
+
+// To be certain that your changes are working, set the geometry to be a cylinder instead:
+GeometryTypeEnum.CylinderGeometry
+```
+> As we said before, you will need to stop the engine and re-run it whenever you _install_ a new project.
+> But you can just refresh the webpage when you update your source code and the engine will load your changes correctly.
+
+:::note
+`VSCode` is the recommended editor for programming with Ethereal Engine.
+It is not required, but it is highly recommended.
+VSCode has support for some important features and plugins that make the Ethereal Engine programming workflow really smooth and featureful.
+:::
+
+
+
+The imports section of our code will now be:
+```ts title="ee-tutorial-hello/src/Hello.ts"
+// ... our other imports
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { Vector3 } from 'three'
+// highlight-start
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+// highlight-end
+```
+The `PrimitiveGeometryComponent` call will now be:
+```ts title="ee-tutorial-hello/src/Hello.ts"
+const entity = ECS.createEntity()
+// ... our other calls to setComponent
+// highlight-start
+ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+// highlight-end
+```
+
+
+
+```ts title="ee-tutorial-hello/src/Hello.ts" showLineNumbers
+import { ECS } from '@etherealengine/ecs'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+// highlight-start
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+// highlight-end
+
+const entity = ECS.createEntity()
+ECS.setComponent(entity, NameComponent, 'hello-world')
+ECS.setComponent(entity, VisibleComponent)
+ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+// highlight-start
+ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+// highlight-end
+```
+
+
+
+
+
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/03_system.md b/docs/developer/typescript/01_gettingStarted/02_hello/03_system.md
new file mode 100644
index 000000000000..234f106c6382
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/03_system.md
@@ -0,0 +1,181 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Systems
+If you have a keen eye you may have noticed something really important.
+We are using the `Entity Component System` pattern, and so far:
+- We created an `Entity`
+```ts
+const entity = ECS.createEntity()
+```
+- We added `Components` to our Entity...
+```ts
+ECS.setComponent(entity, NameComponent, 'hello-world')
+ECS.setComponent(entity, VisibleComponent)
+ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: 1 })
+```
+- And then we asked Ethereal Engine to run our code...
+
+## Wait, where is the System?
+But we never defined a `System`!
+
+In the quickstart tutorial we used a simplified code example for brevity and ease of understanding.
+But we also broke Ethereal Engine's best practices in order to achieve that simplicity.
+So, lets fix that.
+
+
+The root of the problem is that we have [created and modified](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) our data inside module scope.
+This is an anti-pattern. [Data Mutation](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations should always occur in a [Controlled Context](/manual/modules/engine/ecs), and the module's top level scope is not such.
+
+
+## Our first System
+As we mentioned in the [ECS Pattern](./ecs) section earlier, `Systems` are used to define the logic and behavior of our application.
+But, in order to make the example easier to understand, we cheated a little bit and broke the engine's best practices.
+
+The correct way to create the Sphere of our minimal example would be to:
+- Create a function that will create our Sphere.
+- Define a `System` that will `execute` our function.
+- Insert the System into the engine so that it is run right after the engine's `PhysicsSystem`.
+
+### Our function
+So far we have been defining the code that creates our Sphere at the top level of our module.
+This means that we relied on the module being imported when the project configuration is loaded.
+But the correct way to do this is to define our code inside a separate function, and give that function to the `execute` parameter of a System created with `defineSystem`.
+
+Lets start by creating a new Typescript function, and moving our ECS code into that function.
+```ts
+// Create a function
+function /* name */ () { /* code */ }
+```
+We will also need to make sure that our code is only run once.
+Try to figure out a way to make your function code execute only once before looking at the solution.
+_hint: You won't need any special engine modules for this. Just regular Typescript will work._
+
+
+
+```ts
+//highlight-start
+let initialized = false // Track whether our code was already initialized or not
+//highlight-end
+
+//highlight-start
+function hello() { // Define a function that will run our code
+ if (initialized) return // Exit early if the code was already run before
+ initialized = true // Mark initialized to true, so the code is never run again later
+//highlight-end
+
+ // Create the Sphere object.
+//highlight-start
+ // Same code as before, but now it runs inside our function
+//highlight-end
+ const entity = ECS.createEntity()
+ ECS.setComponent(entity, NameComponent, 'hello-world')
+ ECS.setComponent(entity, VisibleComponent)
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+}
+```
+
+There are other ways to keep track of state than manually maintaining our `initialized` variable.
+- A state variable with `Hyperflux`
+- A reactor mount with `useEffect`
+
+But our `initialized` variable will keep things simple and minimal for the purpose of this tutorial.
+We will learn how properly manage state later on.
+
+
+
+
+:::note
+We are using a regular Typescript function in this example.
+You could also use a Typescript arrow function if you prefer.
+Both styles work perfectly well.
+:::
+
+
+
+
+
+### The `defineSystem` function
+In order to define a new system, we need to use the `defineSystem` function from the `ECS` namespace.
+
+This is what we need to know to use this function:
+- `defineSystem` will return the identifier that represents our `System`
+- We need to `export` that type so that the engine can access it
+- We need to pass our function into the `execute` argument
+- We don't need to add any new imports. The `defineSystem` function is available through the `ECS` namespace
+- We will use the `insert` argument to tell the engine when we want our code to run
+
+I already filled in some parts of the code. Try to fill in the rest by yourself before looking at the solution.
+```ts
+/* ... */ = ECS.defineSystem({
+ uuid: /* ... */, // The unique id of our System. Could be a string or a number.
+ execute: /* ... */, // The function that will run our code
+ insert: { after: PhysicsSystem } // Tell the engine to run the system after the PhysicsSystem
+})
+```
+:::note
+The engine will take care of executing our code when it is correct to do so, based on the value we passed into the `insert` argument.
+:::
+
+
+
+```ts title="ee-tutorial-hello/src/Hello.ts"
+//highlight-start
+export const HelloWorldSystem = ECS.defineSystem({
+ uuid: 'helloworld.system',
+ execute: hello,
+//highlight-end
+ insert: { after: PhysicsSystem }
+})
+```
+
+
+## Conclusion
+This is how our final code will look like after we have completed these tasks.
+
+
+
+```ts title="ee-tutorial-hello/src/Hello.ts" showLineNumbers
+import { ECS } from '@etherealengine/ecs'
+import { PhysicsSystem } from '@etherealengine/spatial/src/physics/PhysicsModule'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { Vector3 } from 'three'
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+
+
+//highlight-start
+let initialized = false // Track whether our code was already run or not
+//highlight-end
+
+//highlight-start
+// Our new function
+function hello() {
+ if (initialized) return
+ initialized = true
+ //highlight-end
+
+ //highlight-start
+ // Create the Sphere object inside our function.
+ //highlight-end
+ const entity = ECS.createEntity()
+ ECS.setComponent(entity, NameComponent, 'hello-world')
+ ECS.setComponent(entity, VisibleComponent)
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+}
+
+//highlight-start
+// Define our System
+export const HelloWorldSystem = ECS.defineSystem({
+ uuid: 'helloworld.system',
+ execute: hello,
+ insert: { after: PhysicsSystem }
+})
+//highlight-end
+```
+
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/04_component.md b/docs/developer/typescript/01_gettingStarted/02_hello/04_component.md
new file mode 100644
index 000000000000..722be5aea953
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/04_component.md
@@ -0,0 +1,112 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Components
+Ok, lets admit the truth.
+We have cheated with something else.
+
+You might have noticed already, but we are creating a Sphere for **every scene**.
+Open any other project with the engine, and you will see that our ball is also there!
+That's not good. Whoops.
+
+## Our Problem
+We have setup our Sphere code to be simple and minimal.
+This is what we have done so far:
+- We created a file called `src/Hello.ts` that contains our code
+- We connected our code to the engine with the project's configuration file
+- We defined a system at module scope using `defineSystem`
+- We never defined our Sphere as a Component _(whoops)_
+- We never added our Sphere Component to a specific Scene
+ _(well, we didn't have a Sphere Component, so we couldn't)_
+
+These two last steps are the key to our problem.
+This happens because the engine will execute projects globally, but we are not restricting our code to be run only when requested.
+
+So our example, up until now, has been acting as if it was an extension to the Studio editor!
+
+
+A more technical description of our problem is that our example is not using the engine API properly.
+Execution of projects is global and meant to be data oriented.
+But the data weβre relying on in our example is created within the project, instead of being triggered by actions from our users.
+
+
+## Our Solution
+The proper way to add our simple Sphere would be to lock our logic behind a custom Scene Component.
+That way, when a component is added to an entity, the system can be activated through a query.
+
+Solving this correctly will require us to use all of these new concepts:
+- Defining a Custom Component
+- Defining a Query for our Component
+- Manage our `initialized` variable from inside our Component
+- Connect our Sphere such that it is loaded only for a specific Scene
+
+This section is quite complex, and we are going to properly explore all of these concepts in the following tutorials. So, for now, the assignments are going to be very simple.
+We will leave the explanations for the [Ethereal Engine Basics](/developer/typescript/basics) guide.
+
+## Creating a Custom Component {#create}
+You can probably already guess the name of the function we are going to use next.
+The function for **defining a Component** is called...
+
+`defineComponent`, which its part of the namespace... `ECS`
+
+
+:::note
+I will fill in the difficult parts for this assignment, as I don't expect you to be able to magically know these things just yet.
+We will do that on the next tutorial!
+:::
+
+Here are your hints for completing this task:
+```ts
+// Define our component
+export ... = ... ({
+ name: ...,
+ jsonID: 'EE_tutorial_hello',
+ onInit: () => { return { initialized: false } }
+})
+```
+
+
+```ts
+// Define our component
+export const HelloComponent = ECS.defineComponent({
+ name: 'ee.tutorial.HelloComponent',
+ jsonID: 'EE_tutorial_hello',
+ onInit: () => { return { initialized: false } }
+})
+```
+Pay attention to the format of the `name` and `jsonID` fields.
+We haven't talked about this convention, but we will do so later on.
+
+
+You won't see any changes if you run the project as it is now.
+We haven't connected the Component to anything just yet!
+
+## State Management
+We haven't talked much about State, and there is a lot to explain about it.
+We will have an entire section explaining state management in the [Ethereal Engine Basics](/developer/typescript/basics/state) guide.
+
+I will give you this one for free.
+This is the code that replaces our `initialized` variable from the previous page:
+```ts
+// Check if we have already initialized our Sphere
+let { initialized } = ECS.getMutableComponent(entity, HelloComponent)
+if (initialized.value) continue
+initialized.set(true) // Set our initialized state to true
+```
+
+Note how we wrote `if (initialized.value)` instead of just `if (initialized)`.
+And we are modifying its value with `initialized.set(true)` instead of `initialized = true`.
+We will explain why this is the case in the [Ethereal Engine Basics: State](/developer/typescript/basics/state) section.
+
+
+This code will be very useful for our next few steps.
+Don't dwell too much on where to place it just yet. I will give you better instructions for doing that later when we need it.
+
+
+Notice how there is a [`continue`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue) statement in the second line.
+[`continue`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue) is a keyword that only works inside of a loop _(eg: A `for` loop)_.
+Remember that for later.
+
+
+Lets see how we can lock our code to be run only under a specific condition.
+
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/05_query.md b/docs/developer/typescript/01_gettingStarted/02_hello/05_query.md
new file mode 100644
index 000000000000..c67940e05479
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/05_query.md
@@ -0,0 +1,248 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Queries
+Queries are a tool provided by the `Entity Component System` pattern used by Ethereal Engine.
+
+In simple terms, a Query is a function that will request all entities that match a certain condition.
+More specifically, it will return **all** entities that contain **all** Components in the list that we specify.
+
+## Creating a Query
+We are going to **define a Query**. I think you can figure out the name of the function already :)
+This is how the function works:
+- We give the function an [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of Components
+- The function will give us back a Query function
+- We can call the given function to retrieve all entities that contain the components that we specified.
+
+:::note[notes]
+1. We need to send an array anyway, even if it only contains a single Component.
+2. The Query will match only those entities that contain **all** components in our list.
+3. We don't need to export the Query function, as it will only be called by our own code.
+:::
+
+Here are your hints for this assignment:
+```ts
+// Define the query that will find our Scene's Entity
+const queryName = NAMESPACE.funtionName([ CustomComponentName ])
+```
+
+
+
+```ts
+// Define the query that will find our Scene's Entity
+const helloQuery = ECS.defineQuery([HelloComponent])
+```
+
+Same as before, if you run the project as it is now you won't see any changes just yet.
+We have defined the Query that will search for our Scene's entity, but we haven't called it yet.
+
+## Using our Query
+A Query, when called, will return a [JavaScript Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#generator_functions).
+This Generator can be used to access the list of all entities that match the list of Components that we specified.
+
+This means that we can access as many entities as we want from a single unified place!
+Really powerful.
+
+I gave you one solution for free earlier, but I'm leaving this assignment a bit ambiguous on purpose.
+I will give you three options. Pick the one that fits your learning style best:
+1. Challenge:
+ See if you can figure out which part of your code goes where before looking at the solution or the hints. It will be very difficult.
+2. Intermediate difficulty:
+ Open each hint one by one, and take some time to reason about what the hint is trying to say before opening the next one.
+ You might land on the solution earlier than you think.
+3. Otherwise:
+ Read the hints, try to understand them a bit, and then compare what you thought with the full solution.
+
+Here are your hints:
+```ts
+// Our for loop will look something like this
+for (const entity of /* queryName() */) {
+ // Our code goes here ...
+}
+```
+
+
+This step is really difficult without hints. Don't worry if you cannot figure it out on your own.
+There is a lot to process, so what matters most is that you think it through.
+
+
+Generators are called as if they were functions with no arguments, and they will [`yield`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield) the next entry of the list on every iteration.
+
+So, our `for` loop should say:
+```ts
+for (const entity in helloQuery()) {
+ // do something for every entity
+}
+```
+
+
+We cannot store our `initialized` variable in module scope anymore.
+And the code right above cannot be at the top level of your file either.
+It **must** be inside a function.
+
+
+Remember the hint from earlier about the `continue` keyword?
+If not, [go back](./component#state-management) and read it again. You really need it now.
+
+
+Now is the moment when you need to add the code that I gave you "for free" earlier.
+Notice how the hint code above is giving you a `for` loop, and the State Management code has a `continue` keyword. They go together.
+
+
+The `initialized` variable from before cannot exist anymore.
+The state management code replaces it.
+
+
+The state management code **must** be placed inside our `execute` function.
+
+
+We need to execute some code for an entity, just like we did before.
+That hasn't changed.
+
+But you cannot use `createEntity` anymore.
+The entity is `requested` by the Query, not created.
+
+> The `hello-final` scene already contains the entity.
+> Scroll down to the `Loading the Component` section right below if you are confused as to why this is the case.
+
+
+
+1. Import the engine modules
+2. Define a Component
+3. Define a Query that will request entities that contain that Component
+4. Create a function that runs our code
+5. Loop through all entities, and do something for each
+ _(We only have one, but we loop anyway)_
+6. Make sure that we only execute our code once for each entity
+7. Define a System
+8. Set our function as the System's `execute` function
+
+You already have the code for #1, #2, #3, #6 and #7 from before.
+We are creating #4 with this step.
+We are also modifying #5:
+- The initialized variable is replaced with the State Management code I gave you
+- The State Management code **must** placed inside the new #4 loop
+
+
+
+
+
+```ts
+function hello() {
+ //highlight-start
+ for (const entity of helloQuery()) {
+ //highlight-end
+
+ //highlight-start
+ // Check if we have already initialized our Sphere
+ let { initialized } = ECS.getMutableComponent(entity, HelloComponent)
+ if (initialized.value) continue
+ initialized.set(true) // Set our initialized state to true
+ //highlight-end
+
+ ECS.setComponent(entity, NameComponent, 'ee.tutorial.hello-entity')
+ ECS.setComponent(entity, VisibleComponent)
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+ }
+}
+```
+
+
+```ts title="ee-tutorial-hello/src/Hello.ts" showLineNumbers
+import { ECS } from '@etherealengine/ecs'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { Vector3 } from 'three'
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+import { PhysicsSystem } from '@etherealengine/spatial'
+
+// Define our component
+//highlight-start
+export const HelloComponent = ECS.defineComponent({
+ name: 'ee.tutorial.HelloComponent',
+ jsonID: 'EE_tutorial_hello',
+ onInit: () => { return { initialized: false } }
+})
+//highlight-end
+
+// Define the query that will find our Scene's Entity
+//highlight-start
+const helloQuery = ECS.defineQuery([HelloComponent])
+//highlight-end
+
+const hello = () => {
+ //highlight-start
+ for (const entity of helloQuery()) {
+ // Check if we have already initialized our Sphere
+ let { initialized } = ECS.getMutableComponent(entity, HelloComponent)
+ if (initialized.value) continue
+ initialized.set(true) // Set our initialized state to true
+ //highlight-end
+
+ ECS.setComponent(entity, NameComponent, 'ee.tutorial.hello-entity')
+ ECS.setComponent(entity, VisibleComponent)
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+ }
+}
+
+// Define our system
+export const HelloSystem = ECS.defineSystem({
+ uuid: 'ee.tutorial.HelloSystem',
+ execute: hello,
+ insert: { after: PhysicsSystem }
+})
+```
+Notice how I have changed the code to use an arrow function.
+They can be used interchangeably, so feel free to use either of them.
+
+Also, notice how the style of the names in this solution has been changed.
+We will learn about them next.
+
+
+
+
+## Loading the Component
+Now, here is a question:
+> How do we connect our custom scene Component to the scene?
+
+The answer is that there is one last piece of the project that we haven't talked about just yet.
+You might have even seen it in the Studio already if you explored a bit!
+
+We don't know how to add a Component to an entity through the Studio yet, or how to make our Component show up on the `Add Component` Studio UI.
+And we have gone through two entire pages with a LOT of theory but not a whole lot of practice.
+So I already solved this problem for you.
+
+When you open the `ee-tutorial-hello` project... there is a scene called `hello-final` in there.
+That's what we are looking for :)
+
+Thanks to how the `hello-final` scene is setup, our Component will work in that Scene... but it will not work anywhere else! Really neat.
+
+
+What I did, exactly, was:
+- I added an entity to the scene
+- I added the component we are Quering for to the entity
+- I saved the scene into the project
+
+This means that, when you installed the project with the Quickstart guide, you also downloaded the final scene that we need.
+
+
+## Confirm the Code
+You will know that you have completed the [Components](./component) and [Queries](./query) tasks correctly if:
+- The behavior has not changed for the `hello-final` scene. You can still see the sphere in the Scene.
+- You open another scene _(eg: `default-project/appartment` provided by the engine)_...
+ and the Sphere is gone!
+
+## Conclusion
+As you can see, we only added around 10 lines of code in these last two pages...
+But we introduced so many new concepts!
+That's the most exciting part about the ECS pattern. You can do **so** much with so little code.
+
+I hope you didn't struggle too much with the last task. I know it was a difficult one.
+But I promise that, now that you have this knowledge, the road ahead will only get easier and easier.
+
+Lets see what we will learn next!
+
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/90_congrats.md b/docs/developer/typescript/01_gettingStarted/02_hello/90_congrats.md
new file mode 100644
index 000000000000..7b1e790e3ad3
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/90_congrats.md
@@ -0,0 +1,34 @@
+---
+pagination_next: developer/typescript/basics/recap/index
+title: What's Next
+---
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# π Congratulations! π
+You have just learned the minimal basics of working with Ethereal Engine using Typescript!
+
+This was an introductory tutorial to teach you the core essentials of the engine as quickly as possible.
+But Ethereal Engine has a lot of features to explore!
+
+## What's Next?
+#### Beginner
+If this is your first time using Ethereal Engine, we have prepared an [Ethereal Engine Basics](/developer/typescript/basics) tutorial for you.
+It will teach you how to start expanding your knowledge of the engine without getting overwhelmed by its complexity.
+Go to the bottom of this page, and click on "Next" to continue with your learning journey!
+
+#### Intermediate
+If you are feeling confident already, you could jump right into the intermediate tutorials.
+Just pick a topic that interests you in the sidebar and continue your journey from there.
+:::note[Intermediate Note]
+Make sure to skim-read the basics section at least once, as it gives an overview of some important concepts that will be used all throughout the other guides.
+:::
+
+#### Advanced
+The [Manual](/manual) is where Ethereal Engine is presented in all of its complexity, without any guard-rails or hand-holding.
+You will also find the [Reference API](https://etherealengine.github.io/etherealengine-docs/api) really useful when writing the code of your application.
+:::note[Advanced Note]
+Make sure to read the `Mastery Toolkit` section at least once.
+It contains a list of important tools that you will need when working with advanced projects.
+:::
+
+
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/_category_.json b/docs/developer/typescript/01_gettingStarted/02_hello/_category_.json
new file mode 100644
index 000000000000..e0d3b8be94f4
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/_category_.json
@@ -0,0 +1,3 @@
+{
+ "position": 02,
+}
diff --git a/docs/developer/typescript/01_gettingStarted/02_hello/index.md b/docs/developer/typescript/01_gettingStarted/02_hello/index.md
new file mode 100644
index 000000000000..651ef46f484b
--- /dev/null
+++ b/docs/developer/typescript/01_gettingStarted/02_hello/index.md
@@ -0,0 +1,58 @@
+---
+sidebar_label: Hello Ethereal
+---
+# Hello World from Ethereal Engine
+The quickstart tutorial helped us create a project and run the engine for the first time.
+
+This is our starting point.
+The Quickstart has automated a lot for us, so lets review what we have.
+
+:::note
+Don't dwell too much on this page.
+This is a quick preview, so please skim read and don't go into too much detail.
+The purpose of the next few pages of this tutorial is to teach you how these concepts work.
+:::
+
+## Hello World Code
+This is how the code for our project looks like at the moment.
+```ts title="ee-tutorial-hello/src/Hello.ts" showLineNumbers
+import { ECS } from '@etherealengine/ecs'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { Vector3 } from 'three'
+
+const entity = ECS.createEntity()
+ECS.setComponent(entity, NameComponent, 'hello-world')
+ECS.setComponent(entity, VisibleComponent)
+ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: 1 })
+```
+
+## Conceptual overview
+Conceptually, this is what the example project does:
+- It creates an entity called `hello-world`
+- It gives the entity a primitive geometry component _(a Sphere)_
+- It defines the position of the sphere in the scene
+
+## Technical overview
+In technical terms, this is what the example's source code does:
+- It imports some Ethereal Engine's typescript modules in its code
+- It uses the `ECS` pattern
+- It creates an `Entity`
+- It adds a few `Components` to the Entity
+- It adds its code to the engine through the `xrengine.config.ts` file
+
+## The Path Forward
+Our example from the quickstart tutorial is as minimal as it can possibly be.
+But there is a lot happening already, as you can see, even in such a minimal example!
+So, the first step we will take is to spend some time understanding how everything in the example works.
+
+Next we will get our hands into the code, and learn how to program with Ethereal Engine.
+
+Then, at the end of this guide, we will have a very minimal project that we can load with the Engine.
+But, more importantly, we will have enough knowledge to be able to continue our learning through the `Ethereal Engine: Basics` guide.
+
+Lets not delay any longer, and get started with our journey!
+
diff --git a/docs/developer/typescript/01_gettingStarted/_category_.yml b/docs/developer/typescript/01_gettingStarted/_category_.yml
index 873ad3e9da76..80ab05bcb8c6 100644
--- a/docs/developer/typescript/01_gettingStarted/_category_.yml
+++ b/docs/developer/typescript/01_gettingStarted/_category_.yml
@@ -1 +1,2 @@
-position: 1
\ No newline at end of file
+label: Getting Started
+position: 1
diff --git a/docs/developer/typescript/01_gettingStarted/index.md b/docs/developer/typescript/01_gettingStarted/index.md
deleted file mode 100644
index ddfa4184f551..000000000000
--- a/docs/developer/typescript/01_gettingStarted/index.md
+++ /dev/null
@@ -1,216 +0,0 @@
-# Getting Started with Typescript
-
-_This guide will teach you how to get started programming with Ethereal Engine using Typescript._
-_Visit the [Typescript: Introduction](/developer/typescript) page for more details._
-
-
-## Overview
-
-We're going to look at 'Pong', a multiplayer game that we've built in Ethereal Engine using Typescript. It is an example of best practices for developers.
-
-## Installation and Running Pong
-
-1) Ethereal Engine scans for projects mounted in the /packages/projects/projects sub-folder of Ethereal Engine. From scratch we can install Ethereal Engine itself and also register a sub project using the following:
-
-```
-gh repo clone EtherealEngine/EtherealEngine
-cd EtherealEngine
-cd packages/projects/projects
-gh repo clone EtherealEngine/ee-tutorial-pong
-cd ../../../
-```
-
-2) A fresh install of Ethereal Engine can be run like so:
-
-```
-npm install
-npm run dev
-```
-
-3) Once Ethereal Engine itself is running, from the web admin panel of Ethereal Engine create a 'location' for the project. See https://localhost:3000/admin . Map the project to the name 'pong'.
-
-4) Run the project on the web by visiting it with the URL you created. See https://localhost:3000/location/pong
-
-## Understanding Pong
-
-### A 10000 foot overview
-
-Pong has several files which are roughly represent parts of the experience:
-
-- PaddleSystem -> a paddle 'system' for managing the player paddles specifically.
-- PlateComponent -> each pong game has one or more plates that represent player positions in a game. In our case we have 4 player games.
-- PongComponent -> each pong game in a larger pong world has a concept of a game starting or stopping; this is managed here.
-- PongGameSystem -> a game 'system' for managing each game instance; starting and stopping play and dealing with players.
-- PongPhysicsSystem -> a ball spawner and scoring 'system' for the pong game overall
-- worldinjection -> bootstraps the game
-
-A 'Pong' world can have several separate pong tables at once. Each pong table has four pong plates and can handle four players at once.
-
-### World Injection
-
-Ethereal Engine projects typically have a worldinjection.ts file to bootstrap a project. In Pong this file registers and starts three 'systems', and does little else:
-
-```
-import './PaddleSystem'
-import './PongGameSystem'
-import './PongPhysicsSystem'
-export default async function worldInjection() {}
-```
-
-### Entities, Components and Systems
-
-Ethereal Engine uses an ECS (Entity Component System). Entities in a game are entirely defined by their Components or 'capabilities', and systems driven the state of the entire application over time by running every frame over those components. One benefit of an ECS is that it allows a highly granular 'vocabulary' for designers to express game ideas with.
-
-The ECS we use currently BitECS. Another good ECS is Flecs:
-
-- https://github.com/NateTheGreatt/bitECS
-- https://news.ycombinator.com/item?id=35434374
-
-In Pong there are three systems imported via worldInjection above. Each is responsible for a different part of the experience:
-
-1) PaddleSystem
-2) PongPhysicsSystem
-3) PongGameSystem
-
-We will look at the PaddleSystem.ts first.
-
-### PaddleSystem: Introduction to State and Reactivity
-
-Ethereal Engine uses the React pattern of allowing state observers to 'react' to state changes. This is done for a couple of different reasons. Philosophically it separates the 'what' from the 'how', and technically it helps decouple game components from each other, allowing developers to scale work horizontally, reducing dependencies.
-
-The React website has several good discussions on reactivity as a whole:
-
-- https://react.dev/learn/reacting-to-input-with-state
-
-In Pong each active player has two paddles (one for the left hand and one for the right hand), and paddles are spawned or destroyed as players come and go. In this case the 'what' is that there are some set of paddles. And the 'how' (which we will get to later) is that the paddles happen to be 3d objects with collision hulls. But at this level of scope we can separate our concerns and we don't have to think about how the paddles are manifested.
-
-In PaddleSystem.ts we see a good example of this reactive state pattern. The approach we've taken here is to track the enumeration of active paddles like so:
-
-```
-export const PaddleState = defineState({
- name: 'ee.pong.PaddleState',
- initial: {} as Record<
- EntityUUID,
- {
- owner: UserID
- handedness: 'left' | 'right'
- gameEntityUUID: EntityUUID
- }
- >
- ...
-```
-
-The defineState() method registers a collection of Record objects. A Record is a schema in a third party runtime schema definition language that Ethereal Engine uses.
-
-### PaddleSystem: Introduction to Event Sourced State
-
-Ethereal Engine uses an event sourced state paradigm. Sourcing state and responding to that state is asynchronous but a single 'effect' or outcome results, rather than having to propagate potentially thousands of successive state changes.
-
-A good discussion of Event Sourcing can be found here:
-
-https://domaincentric.net/blog/event-sourcing-snapshotting
-
-In an Event Sourced system, the current state of an aggregate is usually reconstituted from the full history of events. It means that before handling a command we need to do a full read of a single fine-grained stream and transport the events over the network. This allows late joiners to synchronize with the overall game state.
-
-In PaddleSystem we define a set of actions explicitly like so:
-
-```
-export class PaddleActions {
- static spawnPaddle = defineAction({
- ...WorldNetworkAction.spawnObject.actionShape,
- prefab: 'ee.pong.paddle',
- gameEntityUUID: matchesEntityUUID,
- handedness: matches.literals('left', 'right'),
- owner: matchesUserId,
- $topic: NetworkTopics.world
- })
-}
-```
-
-And we then allow the registration of 'receptors' on state objects to catch dispatched events over the network, and in this case we're entirely focused on updating the state records above:
-
-```
- ...
- receptors: [
- [
- PaddleActions.spawnPaddle,
- (state, action: typeof PaddleActions.spawnPaddle.matches._TYPE) => {
- state[action.entityUUID].merge({
- owner: action.owner,
- handedness: action.handedness,
- gameEntityUUID: action.gameEntityUUID
- })
- }
- ],
- [
- WorldNetworkAction.destroyObject,
- (state, action: typeof WorldNetworkAction.destroyObject.matches._TYPE) => {
- state[action.entityUUID].set(none)
- }
- ]
- ]
-})
-```
-
-The WorldNetworkAction.destroyObject is an observer we've injected here to catch here to make sure that we update our state tables appropriately. Although we have custom state on the object creation, we don't have any custom state on paddle destruction.
-
-### PaddleState: Introduction to Components
-
-With the state management out of the way, now we're left with the details of making sure our visual representations reflect our state.
-
-PaddleReactor defines a React component that has a useEffect() to observe state changes on a given PaddleState entry. When the PaddleState changes it sets up an entity to reflect that owner. Inside the useEffect() we see several typical 3d and game related components being setup:
-
- - UUIDComponent
- - TransformComponent
- - VisibleComponent
- - DistanceFromCameraComponent
- - FrustrumCullComponent
- - NameComponent
- - PrimitiveGeometryComponent
- - ColliderComponent
- - GrabbableComponent
-
-Most of these components are self descriptive, and this typically reflects the core set of components you'll see in many Ethereal Engine 3d entities that represent objects in a game.
-
-The GrabbableComponent is notable in that it's a good example of where components are more than just 'state'; they can be used to form an expressive 'vocabulary' of high level intentions. In this case we want the paddle to stay attached to the owner avatar at a specified attachment point. If we didn't have this concept we would have to fire rigid body physics target position events every frame to keep the paddle synchronized with the player.
-
-### PaddleState: Introduction to Reactors
-
-Both PaddleReactor and Reactor in PaddleSystem demonstrate reactivity to state. The reactor is updated whenever state changes, and the game entities that exist are a reflection of that larger state.
-
-### PaddleState: System
-
-Tying everything together in PaddleSystem is the PaddleSystem itself. It registers and runs an execute() handler every frame and it also registers the reactor:
-
-```
-export const PaddleSystem = defineSystem({
- uuid: 'pong.paddle-system',
- execute,
- reactor,
- insert: { after: PhysicsSystem }
-})
-```
-
-### PaddleState: Overall Flow
-
-The general flow is like so:
-
-1) The execute handler catches and handles PaddleActions using ```receiveActions(PaddleState)```
-
-2) The PaddleActions respond to network events and applies them to the PaddleState.
-
-3) The reactor reacts to any state changes on PaddleState.
-
-## PlateComponent
-
-
-### PongComponent, PongGameSystem and PongPhysicsSystem
-
-
-### Summary
-
diff --git a/docs/developer/typescript/02_basics/01_recap/01_styling.md b/docs/developer/typescript/02_basics/01_recap/01_styling.md
new file mode 100644
index 000000000000..71cd26edef4c
--- /dev/null
+++ b/docs/developer/typescript/02_basics/01_recap/01_styling.md
@@ -0,0 +1,164 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Styling
+We took a lot of shortcuts in previous sections of the tutorial.
+This made learning much simpler to get started with, but we also left out a few concepts that will make our codebase much easier to navigate as soon as our project starts growing.
+
+## ID Naming Convention
+Lets start with the simplest style change.
+You may have noticed that we changed the `uuid` and `NameComponent` in the HelloWorld's final solution.
+The engine doesn't have a standard for these names yet, but this is a good naming convention that you can follow:
+- Separate words with `.`
+- Start with the namespace/organization/author of your project
+- Follow by the project name of the thing that you are naming
+- Follow by the name of the thing
+- Separate multi-word names with `-`
+```md
+# Example
+Namespace : ee
+Project : tutorial
+Thing : HelloSystem
+
+Result : ee.tutorial.HelloSystem
+Multi-word : ee.multi-word-example.HelloSystem
+```
+:::note[assignment zero]
+This is not really an assignment, as we already did this before.
+But see if you have any names leftover in your code that are not using this standard, and change them so that they do.
+:::
+
+## `jsonID` Naming Requirements
+You may have also noticed that the `jsonID` field does not respect the naming convention we just explained above.
+Internally, the field `jsonID` will be used to define the name of a [glTF](https://www.khronos.org/gltf) extension.
+As such, the engine has a different standard for them:
+- Separate words and multi-words with `_`
+- Start with the namespace/organization/author of your project in UPPERCASE
+- Follow by the project name of the thing that you are naming
+- Follow by the name of the thing
+```md
+# Example
+Namespace : EE
+Project : tutorial
+Thing : hello
+
+Result : EE_tutorial_hello
+Multi-word : EE_multi_word_example_hello
+```
+
+## Arrow Functions
+We talked about Javascript [`Arrow Functions`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) during one of the earlier sections of the HelloWorld tutorial. They are used a lot throughout the engine's codebase.
+
+They are specially helpful when defining Systems and Components.
+This is how a `defineSystem` call would look like using each type of function:
+```ts title="Regular Function : Simpler, but less common in Ethereal Engine"
+// Our function
+function sayhello() { console.log("Hello World") }
+
+// Our System
+const HelloSystem = ECS.defineSystem({
+ uuid: 'ee.tutorial.HelloSystem',
+ execute: sayhello,
+ insert: { after: PhysicsSystem }
+})
+```
+```ts title="Arrow Function : How defining a multi-field object usually looks like"
+// Our function can be declared inside our system. Doesn't need a name
+const HelloSystem = ECS.defineSystem({
+ uuid: 'ee.tutorial.HelloSystem',
+ execute: () => {
+ console.log("Hello World")
+ },
+ insert: { after: PhysicsSystem }
+})
+```
+
+As you can see, this gives us a very small gain for this tiny example.
+But, when the codebase grows, this style can make a big difference in the readability of our code.
+
+Arrow functions are also used extensively all throughout the engine's codebase.
+So, even if you don't prefer them, at least you need to know about how they work so that you are not confused the first time you find code using this style.
+
+:::important[first assignment]
+Change the style of the BasicsTutorial code:
+. Remove any named functions that are assigned to an object
+. Use arrow functions directly as object fields
+
+There are not that many to change. We only had one named function! :)
+:::
+
+
+
+```ts
+// Define our system
+export const HelloSystem = ECS.defineSystem({
+ uuid: 'ee.tutorial.HelloSystem',
+ //highlight-start
+ execute: () => {
+ //highlight-end
+ for (const entity of helloQuery()) {
+ let { initialized } = ECS.getMutableComponent(entity, HelloComponent)
+ if (initialized.value) continue
+ initialized.set(true)
+
+ ECS.setComponent(entity, NameComponent, 'ee.tutorial.hello-entity')
+ ECS.setComponent(entity, VisibleComponent)
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+ }
+ //highlight-start
+ },
+ //highlight-end
+ insert: { after: PhysicsSystem }
+})
+```
+
+
+```ts title="ee-tutorial-basics/src/step1.ts" showLineNumbers
+import { ECS } from '@etherealengine/ecs'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { Vector3 } from 'three'
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+import { PhysicsSystem } from '@etherealengine/spatial'
+
+// Define our component
+export const HelloComponent = ECS.defineComponent({
+ name: 'ee.tutorial.HelloComponent',
+ jsonID: 'EE_tutorial_hello',
+ onInit: () => { return { initialized: false } }
+})
+
+// Define the query that will find our Scene's Entity
+const helloQuery = ECS.defineQuery([HelloComponent])
+
+// Define our system
+export const HelloSystem = ECS.defineSystem({
+ uuid: 'ee.tutorial.HelloSystem',
+ //highlight-start
+ execute: () => {
+ //highlight-end
+ for (const entity of helloQuery()) {
+ // Check if we have already initialized our Sphere
+ let { initialized } = ECS.getMutableComponent(entity, HelloComponent)
+ if (initialized.value) continue
+ initialized.set(true) // Set our initialized state to true
+
+ ECS.setComponent(entity, NameComponent, 'ee.tutorial.hello-entity')
+ ECS.setComponent(entity, VisibleComponent)
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 1, 0) })
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+ }
+ //highlight-start
+ },
+ //highlight-end
+ insert: { after: PhysicsSystem }
+})
+```
+
+
+
+
+
diff --git a/docs/developer/typescript/02_basics/01_recap/02_component.md b/docs/developer/typescript/02_basics/01_recap/02_component.md
new file mode 100644
index 000000000000..f45a6283c6a4
--- /dev/null
+++ b/docs/developer/typescript/02_basics/01_recap/02_component.md
@@ -0,0 +1,95 @@
+---
+sidebar_label: Custom Component
+---
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Defining a Custom Component
+The `defineComponent` function accepts a `ComponentPartial` that has multiple fields available.
+```ts
+// Define our component
+const HelloComponent = ECS.defineComponent({
+ name: 'ee.tutorial.HelloComponent',
+ jsonID: 'EE_tutorial_hello',
+ onInit: () => { return { initialized: false } }
+})
+```
+
+:::note
+See [Typescript.Partial](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) for a reference of what Partials are.
+:::
+
+Lets review what each of these fields do and how to use them.
+## `name`
+`name` is a `string` that defines the human readable label for the component that we are creating.
+It will be displayed in the editor and debugging tools.
+```ts
+name: 'ee.tutorial.HelloComponent',
+```
+As we saw before, the engine does not define strict naming requirements for this field, but it does define a [naming convention](./styling#id-naming-convention) that is good practice to follow in your projects.
+
+## `jsonID`
+`jsonID` is an optional `string` that defines the internal ID used to reference this component in JSON data.
+```ts
+jsonID: 'EE_tutorial_hello',
+```
+As we saw before, this field will be used by the engine to define the name of a [glTF](https://www.khronos.org/gltf) extension.
+Because of this, the `jsonID` field has very specific [naming requirements](./styling#jsonid-naming-requirements) that must be followed.
+
+## `onInit`
+`onInit` is a function that will be called once when the Component is added to an entity _(ie: initialized)_.
+It returns the shape of the Component's runtime data, which has the type `Schema`.
+```ts
+onInit?: (this: SoAComponentType, entity: Entity) => ComponentType & OnInitValidateNotState
+// this : `@internal` The component partial itself.
+// entity : The Entity to which this Component is being assigned.
+// returns : The `Schema` (aka shape) of the component's runtime data.
+```
+A Component's Schema can contain any type of data that you want.
+In our example from before, we saw how to use this data to store our `initialized` state variable inside the component, instead of storing it in our module.
+
+## Other fields
+The `ComponentPartial` type accepts multiple other fields that we haven't needed for our simple HelloComponent example. These fields are:
+`schema`, `toJSON`, `onSet`, `onRemove`, `reactor`, `errors`.
+
+We will explore them further in later sections of the tutorial.
+
+
+The data used to create a Component with `defineComponent` is declared by the `ComponentPartial` interface.
+This type exists so that some of the properties of Components are optional when defining them, but required during normal use.
+
+This is the shape of the `ComponentPartial` interface, defined in the [`ComponentFunctions.ts`](https://github.com/EtherealEngine/etherealengine/blob/dev/packages/ecs/src/ComponentFunctions.ts) file:
+```ts
+{
+ name: string
+ jsonID?: string
+ onInit?: (this: SoAComponentType, entity: Entity) => ComponentType & OnInitValidateNotState
+
+ // A Component's Schema is the shape of its runtime data.
+ schema?: Schema
+
+ // Serializer function called when the component is saved to a snapshot or scene file.
+ // Its logic must convert the component's runtime data into a JSON object.
+ // entity : The Entity to which this Component is assigned.
+ // component : The Component's global data (aka State).
+ toJSON?: (entity: Entity, component: State) => JSON
+
+ // Called when the component's data is updated via the setComponent function.
+ // This is where deserialization logic should happen.
+ // entity : The Entity to which this Component is assigned.
+ // component : The Component's global data (aka State).
+ // json : The JSON object that contains this component's serialized data.
+ onSet?: (entity: Entity, component: State, json?: SetJSON) => void
+
+ // Called when the Component is removed from an Entity
+ onRemove?: (entity: Entity, component: State) => void | Promise
+
+ // Defines the React.FC (Function Component) async logic of the resulting Component type.
+ // Any side-effects that depend on the component's data should be defined here.
+ reactor?: React.FC
+
+ errors?: ErrorTypes[]
+}
+```
+
+
diff --git a/docs/developer/typescript/02_basics/01_recap/03_query.md b/docs/developer/typescript/02_basics/01_recap/03_query.md
new file mode 100644
index 000000000000..8e782b3953ed
--- /dev/null
+++ b/docs/developer/typescript/02_basics/01_recap/03_query.md
@@ -0,0 +1,22 @@
+---
+sidebar_label: Query
+---
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Define a Query
+Queries are the simplest concept to explain out of everything we have dealt with so far.
+But we looked into them only briefly, so lets explore their technical properties anyway.
+
+Ethereal Engine's `defineQuery` is a function that accepts an [`array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of `Component` types, and will return a [JavaScript Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#generator_functions). This `Generator` can then be used in a [`for`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) loop to iterate over **all** entities that contain **all** Components in the list that we provided _(ie: our array of Components)_.
+
+:::note
+The returned Query can be named anything we want, as its name is only relevant for our project.
+:::
+```ts
+const helloQuery = ECS.defineQuery([HelloComponent])
+
+for (const entity of helloQuery()) {
+ // Do something for all entities that contain a HelloComponent
+}
+```
diff --git a/docs/developer/typescript/02_basics/01_recap/04_next.md b/docs/developer/typescript/02_basics/01_recap/04_next.md
new file mode 100644
index 000000000000..998eb348352d
--- /dev/null
+++ b/docs/developer/typescript/02_basics/01_recap/04_next.md
@@ -0,0 +1,33 @@
+# Overview
+The `Hello World` tutorial has taught us how to work with and create the most minimal Ethereal Engine programming example possible. But, as we are about to learn, there is a lot more to explore!
+
+## Hello World
+Lets review what we have achieved with our project. So far we:
+- Imported some Ethereal Engine's typescript modules in our file
+- Created an entity, and gave it an `uuid` and a `name`
+- Gave the entity the ability to:
+ - Be visible on the screen with a `VisibleComponent`
+ - Have Linear Transformations with a `TransformComponent`
+- Defined the position of the sphere in the scene
+- Gave the entity a `PrimitiveGeometryComponent` _(a Sphere)_
+- Defined a Custom `Component` type
+- Defined a `Query` to search for our Custom Component
+- Locked our logic to only happen once with the `initialized` State variable contained inside our Custom Component.
+- Defined a `System` and locked our logic behind its `execute` function
+- Locked our logic to only trigger for the entities that match our `helloQuery` generator
+- Added our project's code to the engine with the `xrengine.config.ts` configuration file
+
+That's a lot!!!
+
+## Ethereal Engine: Basics
+In this tutorial we will expand on our knowledge, and we will add these features to the source code of our project:
+- Physics Properties: Gravity, Collision, Friction, etc
+- Logic that happens every frame at specific intervals _(eg: every fixed-frame or every visual-frame)_
+- State Management _(eg: our `initialized` variable, but better)_
+- Input Management _(keyboard, mouse, touchpad, etc)_
+- How to debug our code to search for errors
+- Networked events and actions that can be shared between multiple devices
+
+And, at the end of the tutorial, we will put everything together into a complete mini-game!
+
+Lets not wait any longer and get started by adding [`Physics`](../physics) to our project.
diff --git a/docs/developer/typescript/02_basics/01_recap/_category_.yml b/docs/developer/typescript/02_basics/01_recap/_category_.yml
new file mode 100644
index 000000000000..d6b968359e12
--- /dev/null
+++ b/docs/developer/typescript/02_basics/01_recap/_category_.yml
@@ -0,0 +1 @@
+position: 01
diff --git a/docs/developer/typescript/02_basics/01_recap/index.md b/docs/developer/typescript/02_basics/01_recap/index.md
new file mode 100644
index 000000000000..5ecd292417a9
--- /dev/null
+++ b/docs/developer/typescript/02_basics/01_recap/index.md
@@ -0,0 +1,12 @@
+import DocCardList from '@theme/DocCardList';
+
+# Quick Recap
+In the last step of the [Hello World Tutorial](/developer/typescript/gettingStarted/hello/component#create) we created a custom Scene Component.
+But we never really explained how we did it.
+
+We also skimmed over multiple concepts that are very important for working with the Engine. So lets start on the right foot and explain them now.
+Also, now that we are into it, we are going to style our code in a way that matches Ethereal Engine's code a bit more.
+
+Lets start with Styling.
+
+
diff --git a/docs/developer/typescript/02_basics/02_physics.md b/docs/developer/typescript/02_basics/02_physics.md
new file mode 100644
index 000000000000..65b0c9a510ea
--- /dev/null
+++ b/docs/developer/typescript/02_basics/02_physics.md
@@ -0,0 +1,127 @@
+---
+sidebar_label: Physics
+---
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Adding Physics
+So far we have learned how to create an `Entity`, and how to tell the engine what we want our entity to be. In simple terms, we told the engine how to **create** our sphere.
+
+## Our problem
+We added some components to our sphere, so that the engine can draw the sphere into the screen and we can see it.
+But right now it is only an "empty shell" that sits there doing nothing.
+We cannot even move it or push it around! What a boring ball.
+Lets fix that.
+
+## Our solution
+We are going to add a Collider and a RigidBody to our sphere object.
+
+Physics properties are tricky to test, as they may not be readily visible.
+Lets get a point of reference of how our project currently behaves, so we can be certain that the changes we make to our code are working as we expect them.
+In order to do that, we are going to run our project from the studio and walk around the scene with an Avatar.
+
+These are the steps needed to accomplish that:
+- Open the scene you created before, or click on `Create Scene` if you don't have it
+- Press the `Play` button in the studio
+- Move your Avatar around the scene by either:
+ - Pressing `WASD` in your keyboard
+ - Clicking anywhere on the ground with your mouse
+
+You may notice that, if you try to hit the sphere with your avatar... you will instead walk right through it!
+This happens because our Sphere doesn't have any Physics properties yet, so it can be "seen" but not "collided against".
+
+## Physics Properties
+In order to correct our problem, we are now going to:
+- Add a `RigidBodyComponent` of type `dynamic` to our entity
+- Add a `ColliderComponent` with the shape of a `sphere`
+
+Lets also change the position of ball so that it spawns some distance above the ground.
+Here are your hints for this tutorial:
+```ts
+// Both the RigidBody and Collider components are part of the `Spatial/physics` engine module
+'@etherealengine/spatial/src/physics/components/.....'
+// We can specify the dynamic type with:
+{ type: 'dynamic' }
+// We can specify the shape with:
+{ shape: 'sphere' }
+// Make the ball spawn 3units above the ground
+Vector3(/* X */, /* Y */, /* Z */)
+```
+
+You will know that your code is correct if:
+- The ball has gravity and falls to the ground
+- You try to go through the ball with the Avatar, but the engine stops you and you push the ball instead.
+
+
+
+```ts
+// Import both components from the Spatial/physics module
+import { RigidBodyComponent } from '@etherealengine/spatial/src/physics/components/RigidBodyComponent'
+import { ColliderComponent } from '@etherealengine/spatial/src/physics/components/ColliderComponent'
+```
+```ts
+// Set both components to our entity
+ECS.setComponent(entity, RigidBodyComponent, { type: 'dynamic' })
+ECS.setComponent(entity, ColliderComponent, { shape: 'sphere' })
+```
+```ts
+// Make the ball spawn 3 units along the Y axis (aka 3u above the ground)
+ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 3, 0) })
+```
+
+
+
+```ts title="ee-tutorial-basics/Step2.ts" showLineNumbers
+import { ECS } from '@etherealengine/ecs'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { Vector3 } from 'three'
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+import { PhysicsSystem } from '@etherealengine/spatial'
+// Import both components from the Spatial/physics module
+//highlight-start
+import { RigidBodyComponent } from '@etherealengine/spatial/src/physics/components/RigidBodyComponent'
+import { ColliderComponent } from '@etherealengine/spatial/src/physics/components/ColliderComponent'
+//highlight-end
+
+export const BasicsComponent = ECS.defineComponent({
+ name: 'ee.tutorial.BasicsComponent',
+ jsonID: 'EE_tutorial_basics',
+ onInit: () => { return { initialized: false } }
+})
+
+const basicsQuery = ECS.defineQuery([BasicsComponent])
+
+export const BasicsSystem = ECS.defineSystem({
+ uuid: 'ee.tutorial.BasicsSystem',
+ execute: () => {
+ for (const entity of basicsQuery()) {
+ let { initialized } = ECS.getMutableComponent(entity, BasicsComponent)
+ if (initialized.value) continue
+ initialized.set(true)
+
+ ECS.setComponent(entity, NameComponent, 'ee.tutorial.basics-entity')
+ ECS.setComponent(entity, VisibleComponent)
+ // Make the ball spawn 3 units along the Y axis (aka 3u above the ground)
+ //highlight-start
+ ECS.setComponent(entity, TransformComponent, { position: new Vector3(0, 3, 0) })
+ //highlight-end
+ ECS.setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+ // Set both components to our entity
+ //highlight-start
+ ECS.setComponent(entity, RigidBodyComponent, { type: 'dynamic' })
+ ECS.setComponent(entity, ColliderComponent, { shape: 'sphere' })
+ //highlight-end
+ }
+ },
+ insert: { after: PhysicsSystem }
+})
+```
+
+
+
+
+
+
diff --git a/docs/developer/typescript/02_basics/03_state.md b/docs/developer/typescript/02_basics/03_state.md
new file mode 100644
index 000000000000..6e13c6e59fbd
--- /dev/null
+++ b/docs/developer/typescript/02_basics/03_state.md
@@ -0,0 +1,126 @@
+---
+sidebar_label: State
+---
+
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+
+# State Management
+We have been talking about the concept of `State`, but we never really explained what it is or how to use it correctly. Lets fix that now.
+
+## What is State
+In Computer Science, [State](https://en.wikipedia.org/wiki/State_(computer_science)) is the concept of remembering information (data) about something that happened earlier in time.
+
+Lets say we want to:
+1. Increment a number every second
+2. Keep incrementing the number until the application stops
+
+We could store the current value of our number inside a variable, and that variable would contain our `State`:
+```ts
+// Simple example of a variable used to track our clock's current state
+let seconds = ...
+```
+
+In this example, our State variable would represent the seconds elapsed.
+We could name it `clock` or `clockSeconds` to make it easier to understand the purpose of the data contained in the variable.
+
+That is exactly what we did with our `initialized` variable from before.
+We needed to run our code only once _(aka when our code is first loaded)_ so we created an `if (initialized)` check that exited our code early when the value was `true`.
+Then, by updating the information contained in our variable to `true`, we created a `State Variable` that remembered whether our code was already initialized or not.
+
+### Local State
+In Computer Science, [Scope](https://en.wikipedia.org/wiki/Scope_(computer_science)) is used to represent the part of the program where a name is valid.
+
+`Module Scope` is one of the many types of `Local Scope` that can exist.
+When a name has Module Scope it means that the variable/function/etc it represents will only be accessible by code in:
+- The file where it is declared
+- A file where the name is imported _(only if the name was defined with `export`)_.
+
+Our `initialized` variable started as a Module Scope variable in the earlier sections of the [Hello World](../gettingStarted/hello/system) tutorial. We declared it at the top-level of our file, so it was `Local State` _(ie: Local to the Module)_.
+```ts
+let initialized = false
+function hello() {
+ if (initialized) return
+ // ... etc
+}
+```
+
+But, later on, we changed our code and moved the variable into our custom scene Component:
+```ts
+export const HelloComponent = defineComponent({
+ ...
+ onInit: () => return { initialized: false }
+})
+```
+With this change, we made our variable accessible anywhere where our Component is accessible.
+This still doesn't make our state `Global`, but it changed the scope from "Local to the Module" to "Local to the Component".
+
+
+### Global State
+So far we have only dealt with Local State
+
+## React State
+Global State in React is any State that can be shared between Components.
+Its purpose is being able to share updatable variables between multiple components. (eg: Accessing a variable from a child component several levels down the component tree) without having to pass their data from component to component _(called "prop-drilling")_.
+
+React provides the [`Context`](https://react.dev/learn/passing-data-deeply-with-context) API for this exact purpose.
+But, as we will explore in a moment, `Hookstate` and Ethereal Engine's `Hyperflux` are much better ways to manage the state of our project.
+
+## Managing State in Ethereal Engine
+There are multiple ways to keep track of state in Ethereal Engine:
+- Manually maintaining the value of a variable
+- A state variable with `Hyperflux`
+- A reactor mount with `useEffect`
+
+### Local Variable
+As you saw, we are fully responsible of book-keeping the values contained in the variables we create this way.
+There are also strict limitations on what these values can be used for.
+
+
+### Ethereal Engine's Hyperflux
+
+#### Hookstate
+Hookstate is a tool created to simplify state management in React applications.
+We can access a vanilla hookstate State definition with the `useState` Hook from Hookstate.
+Same as any other React Hook, we can only call the `useState` hook inside React Components.
+
+The variable returned from `useState` will have:
+1. `get()` method: Allows us to read the data contained in the variable
+2. `set()` method: Allows us to modify the data of the variable
+3. `merge()` method: Allows us to combine the current data with new data in an ergonomic way
+
+#### Hyperflux
+Ethereal Engine provides a group of functions to manage state asynchronously.
+
+### `useEffect`
+We want to do some sort of side-effect whenever something happens.
+1. Everything contained is run every time our application is rendered (aka every update)
+2. Everything contained is run when the component is first "Mounted" (explain mount)
+3. List of values that, whenever they change, the code contained in the `useEffect` function is going to run
+Explain what a reactor mount is
+
+
+
+
+```ts
+/**
+ * Global state that tracks locally spawned or destroyed artifacts by using action receptors
+ */
+
+const BasicState = defineState({
+ name: 'ee.basic.BasicState',
+
+ initial: {} as Record,
+
+ receptors: {
+ onSpawnAction: BasicActions.spawnAction.receive((action) => {
+ const state = getMutableState(BasicState)
+ state[action.entityUUID].merge({})
+ }),
+ onDestroyObject: WorldNetworkAction.destroyObject.receive((action) => {
+ const state = getMutableState(BasicState)
+ state[action.entityUUID].set(none)
+ })
+ }
+})
+
+```
diff --git a/docs/developer/typescript/02_basics/04_loop.md b/docs/developer/typescript/02_basics/04_loop.md
new file mode 100644
index 000000000000..887f04d5fa19
--- /dev/null
+++ b/docs/developer/typescript/02_basics/04_loop.md
@@ -0,0 +1,14 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Engine Loop
+
+
+
+
+
+
diff --git a/docs/developer/typescript/02_basics/05_project/_category_.json b/docs/developer/typescript/02_basics/05_project/_category_.json
new file mode 100644
index 000000000000..7a0f9830ac6e
--- /dev/null
+++ b/docs/developer/typescript/02_basics/05_project/_category_.json
@@ -0,0 +1,3 @@
+{
+ "position": 70,
+}
diff --git a/docs/developer/typescript/02_basics/05_project/index.md b/docs/developer/typescript/02_basics/05_project/index.md
new file mode 100644
index 000000000000..9cdd31b2f005
--- /dev/null
+++ b/docs/developer/typescript/02_basics/05_project/index.md
@@ -0,0 +1,16 @@
+# Hero Project
+
diff --git a/docs/developer/typescript/02_basics/06_inputs.md b/docs/developer/typescript/02_basics/06_inputs.md
new file mode 100644
index 000000000000..81a6d201a844
--- /dev/null
+++ b/docs/developer/typescript/02_basics/06_inputs.md
@@ -0,0 +1,12 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Inputs
+
+
+
+
+
+
diff --git a/docs/developer/typescript/02_basics/50_debugging.md b/docs/developer/typescript/02_basics/50_debugging.md
new file mode 100644
index 000000000000..14f0f5a65aba
--- /dev/null
+++ b/docs/developer/typescript/02_basics/50_debugging.md
@@ -0,0 +1,4 @@
+# Debugging
+## Using Ethereal Engine's Debugger with `\``
+
+## Using the Web Browser's Inspector
diff --git a/docs/developer/typescript/02_basics/50_locations.md b/docs/developer/typescript/02_basics/50_locations.md
new file mode 100644
index 000000000000..43822655733b
--- /dev/null
+++ b/docs/developer/typescript/02_basics/50_locations.md
@@ -0,0 +1,48 @@
+# Locations
+Explain what they are.
+Explain why they are required.
+
+## Create a Location
+There are two ways to create a location for our scene:
+- The `Admin Panel`
+- The `Publish` button inside the Studio Editor
+Lets explore both of them.
+
+### Publish Button
+The easiest way to create a location for the current scene is with the `Publish` button in the Studio.
+Follow these steps to create a new Location:
+- Open your scene in the Studio. Navigate to https://localhost:3000/studio and click on your scene
+- Click on the `Publish` button located at the top-right section of the screen
+- Set the Location name to `hello`
+- Click on `Submit`
+- Run the Location by visiting it with the URL you just created: https://localhost:3000/location/hello
+:::note
+This method is just a quick-link to the `Create Location` menu of the Admin Panel.
+The form opened with the `Publish` button is the same that can be accessed through the [Admin Panel: Locations](https://localhost:3000/admin/locations) section explained below.
+:::
+
+### Admin Panel
+While the Publish button provides a really simple and easy way to create a Location for your Scene, it also lacks functionality beyond just creating a new one.
+
+On the other hand, the [Admin Panel: Locations](https://localhost:3000/admin/locations) section provides utilities to manage your existing locations or edit any of their properties.
+
+#### Creating a Location
+Lets create another Location from Admin Panel. Once Ethereal Engine is running:
+- Navigate to the Admin Panel at https://localhost:3000/admin/locations
+- Click on `Create Location`
+- Set the Location name to `hello2`
+- Select the desired scene that will be assigned to this location.
+- Click on `Submit`
+- Run the Location by visiting it with the URL you just created: https://localhost:3000/location/hello2
+
+#### Editing a Location
+Lets now edit our new Location to point to a different scene and have a different name.
+- Navigate to the Admin Panel at https://localhost:3000/admin/locations
+- Find the `hello2` location we just created
+- Click on `View`
+- Click on `Edit`, so we can change its properties
+- Change the Location name to `new-hello`
+- Change the `Scene` to a different one
+- Click on `Submit`
+- Run the Location by visiting it with the URL you just created: https://localhost:3000/location/new-hello
+
diff --git a/docs/developer/typescript/02_basics/60_networking.md b/docs/developer/typescript/02_basics/60_networking.md
new file mode 100644
index 000000000000..3f607129fa63
--- /dev/null
+++ b/docs/developer/typescript/02_basics/60_networking.md
@@ -0,0 +1,18 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Networking
+
+
+
+
+
+```ts
+spawnEntity( ... )
+```
+
+
+
diff --git a/docs/developer/typescript/02_basics/_category_.yml b/docs/developer/typescript/02_basics/_category_.yml
new file mode 100644
index 000000000000..e34d8cd3b323
--- /dev/null
+++ b/docs/developer/typescript/02_basics/_category_.yml
@@ -0,0 +1 @@
+position: 02
diff --git a/docs/developer/typescript/02_basics/index.md b/docs/developer/typescript/02_basics/index.md
new file mode 100644
index 000000000000..0fe47f1d7425
--- /dev/null
+++ b/docs/developer/typescript/02_basics/index.md
@@ -0,0 +1,12 @@
+---
+sidebar_label: Ethereal Engine Basics
+---
+
+import DocCardList from '@theme/DocCardList';
+
+# Ethereal Engine Basics
+This guide is a continuation of the [Hello World Tutorial](../gettingStarted/hello).
+In this guide you will learn how to start expanding your knowledge of the engine beyond the Quickstart introductory guide.
+
+Lets start with a Quick Recap of what we have done so far.
+
diff --git a/docs/developer/typescript/02_topic1/01_file.md b/docs/developer/typescript/02_topic1/01_file.md
deleted file mode 100644
index 7db4cab12c85..000000000000
--- a/docs/developer/typescript/02_topic1/01_file.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/02_topic1/02_file2.md b/docs/developer/typescript/02_topic1/02_file2.md
deleted file mode 100644
index 7db4cab12c85..000000000000
--- a/docs/developer/typescript/02_topic1/02_file2.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/02_topic1/_category_.yml b/docs/developer/typescript/02_topic1/_category_.yml
deleted file mode 100644
index edbd9a5181e4..000000000000
--- a/docs/developer/typescript/02_topic1/_category_.yml
+++ /dev/null
@@ -1 +0,0 @@
-position: 2
\ No newline at end of file
diff --git a/docs/developer/typescript/02_topic1/index.md b/docs/developer/typescript/02_topic1/index.md
deleted file mode 100644
index 9fd89e26d12c..000000000000
--- a/docs/developer/typescript/02_topic1/index.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic 1
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/03_beyondBasics/01_dataDriven/50_state.md b/docs/developer/typescript/03_beyondBasics/01_dataDriven/50_state.md
new file mode 100644
index 000000000000..4662eedd0e58
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/01_dataDriven/50_state.md
@@ -0,0 +1,3 @@
+# State Management
+- [ ] State management
+- [ ] New synchronous state API
diff --git a/docs/developer/typescript/03_beyondBasics/01_dataDriven/_category_.yml b/docs/developer/typescript/03_beyondBasics/01_dataDriven/_category_.yml
new file mode 100644
index 000000000000..d6b968359e12
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/01_dataDriven/_category_.yml
@@ -0,0 +1 @@
+position: 01
diff --git a/docs/developer/typescript/03_beyondBasics/01_dataDriven/index.md b/docs/developer/typescript/03_beyondBasics/01_dataDriven/index.md
new file mode 100644
index 000000000000..0c4d3eaeb5ec
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/01_dataDriven/index.md
@@ -0,0 +1,14 @@
+
+import DocCardList from '@theme/DocCardList'
+
+# Data Driven Development
+
+
+
diff --git a/docs/developer/typescript/03_beyondBasics/50_continuousDevelopment/_category_.yml b/docs/developer/typescript/03_beyondBasics/50_continuousDevelopment/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/50_continuousDevelopment/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/03_beyondBasics/50_continuousDevelopment/index.md b/docs/developer/typescript/03_beyondBasics/50_continuousDevelopment/index.md
new file mode 100644
index 000000000000..54ba8e7c4828
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/50_continuousDevelopment/index.md
@@ -0,0 +1,19 @@
+# Continuous Development
+
diff --git a/docs/developer/typescript/03_beyondBasics/50_debugging.md b/docs/developer/typescript/03_beyondBasics/50_debugging.md
new file mode 100644
index 000000000000..01d9e901d476
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/50_debugging.md
@@ -0,0 +1,2 @@
+# Debugging
+
diff --git a/docs/developer/typescript/03_beyondBasics/50_projects.md b/docs/developer/typescript/03_beyondBasics/50_projects.md
new file mode 100644
index 000000000000..813d0ebc4554
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/50_projects.md
@@ -0,0 +1,23 @@
+# Project Management
+
+
+
+
diff --git a/docs/developer/typescript/03_beyondBasics/_category_.yml b/docs/developer/typescript/03_beyondBasics/_category_.yml
new file mode 100644
index 000000000000..25aa7709d1ec
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/_category_.yml
@@ -0,0 +1 @@
+position: 03
diff --git a/docs/developer/typescript/03_beyondBasics/index.md b/docs/developer/typescript/03_beyondBasics/index.md
new file mode 100644
index 000000000000..698c79ce99d7
--- /dev/null
+++ b/docs/developer/typescript/03_beyondBasics/index.md
@@ -0,0 +1,10 @@
+import DocCardList from '@theme/DocCardList'
+
+# Beyond the Basics
+
+
+
diff --git a/docs/developer/typescript/03_topic2/01_file.md b/docs/developer/typescript/03_topic2/01_file.md
deleted file mode 100644
index 7db4cab12c85..000000000000
--- a/docs/developer/typescript/03_topic2/01_file.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/03_topic2/02_file2.md b/docs/developer/typescript/03_topic2/02_file2.md
deleted file mode 100644
index 7db4cab12c85..000000000000
--- a/docs/developer/typescript/03_topic2/02_file2.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/03_topic2/_category_.yml b/docs/developer/typescript/03_topic2/_category_.yml
deleted file mode 100644
index 71b6ec9c2427..000000000000
--- a/docs/developer/typescript/03_topic2/_category_.yml
+++ /dev/null
@@ -1 +0,0 @@
-position: 3
\ No newline at end of file
diff --git a/docs/developer/typescript/03_topic2/index.md b/docs/developer/typescript/03_topic2/index.md
deleted file mode 100644
index 90b2818b08d8..000000000000
--- a/docs/developer/typescript/03_topic2/index.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Topic 2
-Lorem ipsum dolor sit amet, officia excepteur ex fugiat reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex esse exercitation amet. Nisi anim cupidatat excepteur officia. Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate voluptate dolor minim nulla est proident. Nostrud officia pariatur ut officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit commodo officia dolor Lorem duis laboris cupidatat officia voluptate. Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea consectetur et est culpa et culpa duis.
diff --git a/docs/developer/typescript/04_ecs/01_components/_category_.yml b/docs/developer/typescript/04_ecs/01_components/_category_.yml
new file mode 100644
index 000000000000..d6b968359e12
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/01_components/_category_.yml
@@ -0,0 +1 @@
+position: 01
diff --git a/docs/developer/typescript/04_ecs/01_components/index.md b/docs/developer/typescript/04_ecs/01_components/index.md
new file mode 100644
index 000000000000..ab9412bb7b2b
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/01_components/index.md
@@ -0,0 +1,53 @@
+---
+sidebar_label: Components
+---
+# Working with Components
+## Custom Components
+
+
+
+## `defineComponent` fields
+### `onInit`
+`(entity: Entity) => ComponentType`
+**onInit** is a function that is called when **setComponent** is called on an entity that does not have the component in question.
+It takes an entity number, and should return an object with the initial values for the component.
+
+
+### `onSet`
+`(entity: Entity, component: ComponentType, json: SerializedComponentType) => void`
+**onSet** is a function that is called each time **setComponent** is called.
+It takes an `entity` number, a `component` object and a `json` object.
+
+This function provides a method for reactive data to be updated in batch _(such as deserializing scene data)_, which allows for a much tighter data flow.
+
+
+### `onRemove`
+`(entity: Entity, component: ComponentType) => void`
+**onRemove** is a function that is called when **removeComponent** is called on an entity that has the component in question.
+It takes an `entity` number and a `component` object.
+
+This function is where any resources associated with the component should be cleaned.
+
+
+### `toJSON`
+`(entity: Entity, component: ComponentType) => SerializedComponentType`
+**toJSON** is a function that is called when **serializeComponent** is called on an entity that has the component in question.
+It takes an entity number and a component object.
+
+This function is where the component's data should be serialized _(eg: transforming a scene's data for saving to a file)_.
+
+### `jsonID`
+`string`
+The **jsonID** property is a string that is used to identify the component in json.
+
+It is used for identifying scenes when their data is serialized/deserialized.
+
+### `reactor`
+`function(props: { root: EntityRoot }) => void`
+The **reactor** property specifies a function that exists for the duration of this component instance.
+
+This function is where any effects that depend on the component should be defined.
diff --git a/docs/developer/typescript/04_ecs/02_systems/50_order/01_input.md b/docs/developer/typescript/04_ecs/02_systems/50_order/01_input.md
new file mode 100644
index 000000000000..02bd7210fd2b
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/50_order/01_input.md
@@ -0,0 +1,18 @@
+# Input System
+
diff --git a/docs/developer/typescript/04_ecs/02_systems/50_order/02_simulation.md b/docs/developer/typescript/04_ecs/02_systems/50_order/02_simulation.md
new file mode 100644
index 000000000000..4007e5df5adb
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/50_order/02_simulation.md
@@ -0,0 +1,20 @@
+# Simulation System
+
diff --git a/docs/developer/typescript/04_ecs/02_systems/50_order/03_animation.md b/docs/developer/typescript/04_ecs/02_systems/50_order/03_animation.md
new file mode 100644
index 000000000000..67729110b6e4
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/50_order/03_animation.md
@@ -0,0 +1,27 @@
+# Animation System
+
diff --git a/docs/developer/typescript/04_ecs/02_systems/50_order/04_presentation.md b/docs/developer/typescript/04_ecs/02_systems/50_order/04_presentation.md
new file mode 100644
index 000000000000..5a41a6c77939
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/50_order/04_presentation.md
@@ -0,0 +1,8 @@
+# Simulation System
+
diff --git a/docs/developer/typescript/04_ecs/02_systems/50_order/_category_.yml b/docs/developer/typescript/04_ecs/02_systems/50_order/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/50_order/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/04_ecs/02_systems/50_order/index.md b/docs/developer/typescript/04_ecs/02_systems/50_order/index.md
new file mode 100644
index 000000000000..791542c37642
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/50_order/index.md
@@ -0,0 +1,56 @@
+---
+sidebar_label: Execution Order
+---
+
+import DocCardList from '@theme/DocCardList'
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+
+# Systems Execution Guide
+## Update Loop
+Ethereal Engine uses a very similar model to [Unity's update loop](https://docs.unity3d.com/Manual/ExecutionOrder.html), by the use of a [fixed timestep](https://www.gafferongames.com/post/fix_your_timestep/) update loop.
+
+The engine defines a `frame update` process that is called once per frame.
+Inside this frame-update process there is a `fixed update` process that operates with an `accumulator` pattern.
+This accumulator ensures that time will always step at a stable number of updates per second, independent of the processing power of the hardware running the engine.
+
+_Note: Because the fixed update process is independent of frame updates, each individual frame update may execute 0-to-many fixed updates during its lifetime._
+
+Ethereal Engine implements this feature through system **pipelines**, which are collections of systems that will be executed in a specific order.
+
+
+## Execution Order
+
+
+
+
+```ts
+export const InputSystemGroup = defineSystem({
+ uuid: 'ee.engine.input-group',
+ insert: {}
+})
+
+/** Run inside of fixed pipeline */
+export const SimulationSystemGroup = defineSystem({
+ uuid: 'ee.engine.simulation-group',
+ timeStep: 1 / 60,
+ insert: {}
+})
+
+export const AnimationSystemGroup = defineSystem({
+ uuid: 'ee.engine.animation-group',
+ insert: {}
+})
+
+export const PresentationSystemGroup = defineSystem({
+ uuid: 'ee.engine.presentation-group',
+ insert: {}
+})
+
+export const DefaultSystemPipeline = [
+ InputSystemGroup,
+ SimulationSystemGroup,
+ AnimationSystemGroup,
+ PresentationSystemGroup
+]
+```
+
diff --git a/docs/developer/typescript/04_ecs/02_systems/_category_.yml b/docs/developer/typescript/04_ecs/02_systems/_category_.yml
new file mode 100644
index 000000000000..e34d8cd3b323
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/_category_.yml
@@ -0,0 +1 @@
+position: 02
diff --git a/docs/developer/typescript/04_ecs/02_systems/index.md b/docs/developer/typescript/04_ecs/02_systems/index.md
new file mode 100644
index 000000000000..165d80b94ef2
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/02_systems/index.md
@@ -0,0 +1,9 @@
+---
+sidebar_label: Systems
+---
+
+import DocCardList from '@theme/DocCardList'
+
+# Working with Systems
+
+
diff --git a/docs/developer/typescript/04_ecs/03_queries/_category_.yml b/docs/developer/typescript/04_ecs/03_queries/_category_.yml
new file mode 100644
index 000000000000..25aa7709d1ec
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/03_queries/_category_.yml
@@ -0,0 +1 @@
+position: 03
diff --git a/docs/developer/typescript/04_ecs/03_queries/index.md b/docs/developer/typescript/04_ecs/03_queries/index.md
new file mode 100644
index 000000000000..fc0556e1fd97
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/03_queries/index.md
@@ -0,0 +1,21 @@
+# Queries
+Queries are used to select entities that have a specific set of components.
+They are used to define the entities that a system will operate on.
+
+Queries are defined using the **defineQuery** function:
+```ts
+const query = defineQuery([TransformComponent, GroupComponent])
+
+const entities = query() // returns an array of entity numbers
+```
+
+Queries also have enter and exit derivatives.
+They are used to define when a combination of components is added or removed from an entity.
+These variations are defined using the **defineEnterQuery** and **defineExitQuery** functions:
+```ts
+const query = defineQuery([TransformComponent, GroupComponent])
+
+const allEntities = query()
+const enterEntities = query.enter()
+const exitEntities = query.exit()
+```
diff --git a/docs/developer/typescript/04_ecs/04_reactors/_category_.yml b/docs/developer/typescript/04_ecs/04_reactors/_category_.yml
new file mode 100644
index 000000000000..25aa7709d1ec
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/04_reactors/_category_.yml
@@ -0,0 +1 @@
+position: 03
diff --git a/docs/developer/typescript/04_ecs/04_reactors/index.md b/docs/developer/typescript/04_ecs/04_reactors/index.md
new file mode 100644
index 000000000000..a31e0eb5331c
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/04_reactors/index.md
@@ -0,0 +1,4 @@
+# Reactors
+
diff --git a/docs/developer/typescript/04_ecs/05_eventSourcing/_category_.yml b/docs/developer/typescript/04_ecs/05_eventSourcing/_category_.yml
new file mode 100644
index 000000000000..25aa7709d1ec
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/05_eventSourcing/_category_.yml
@@ -0,0 +1 @@
+position: 03
diff --git a/docs/developer/typescript/04_ecs/05_eventSourcing/index.md b/docs/developer/typescript/04_ecs/05_eventSourcing/index.md
new file mode 100644
index 000000000000..b027acc06908
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/05_eventSourcing/index.md
@@ -0,0 +1,4 @@
+# Event Sourcing
+
diff --git a/docs/developer/typescript/04_ecs/_category_.yml b/docs/developer/typescript/04_ecs/_category_.yml
new file mode 100644
index 000000000000..081f18c43c06
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/_category_.yml
@@ -0,0 +1 @@
+position: 04
diff --git a/docs/developer/typescript/04_ecs/index.md b/docs/developer/typescript/04_ecs/index.md
new file mode 100644
index 000000000000..47562a6f1ea9
--- /dev/null
+++ b/docs/developer/typescript/04_ecs/index.md
@@ -0,0 +1,8 @@
+import DocCardList from '@theme/DocCardList'
+
+# Entity Component System
+
+
+
diff --git a/docs/developer/typescript/40_inputs/_category_.yml b/docs/developer/typescript/40_inputs/_category_.yml
new file mode 100644
index 000000000000..c3c5db22d9fc
--- /dev/null
+++ b/docs/developer/typescript/40_inputs/_category_.yml
@@ -0,0 +1 @@
+position: 40
diff --git a/docs/developer/typescript/40_inputs/index.md b/docs/developer/typescript/40_inputs/index.md
new file mode 100644
index 000000000000..0bac03a63555
--- /dev/null
+++ b/docs/developer/typescript/40_inputs/index.md
@@ -0,0 +1,6 @@
+# Input Management
+
diff --git a/docs/developer/typescript/40_reactivity/01_state.md b/docs/developer/typescript/40_reactivity/01_state.md
new file mode 100644
index 000000000000..d9fe499dbe1c
--- /dev/null
+++ b/docs/developer/typescript/40_reactivity/01_state.md
@@ -0,0 +1,79 @@
+# State Management
+All of Ethereal Engine's state management uses [Hookstate](https://hookstate.js.org/) and [React](https://react.dev/).
+Together, these tools give reactive, declarative, and controlled state management across any scope.
+
+## Scoped State
+Scoped state can be defined using the `useHookstate` hook.
+This functionality uses vanilla `Hookstate`, and is useful for:
+- State that is only used in a single component
+- State that is only used in a single component tree
+
+```tsx
+import { useHookstate } from '@hookstate/core'
+
+const MyComponent = () => {
+ const state = useHookstate({
+ count: 0
+ })
+ return (
+
+
Count: {state.count}
+
+
+ )
+}
+```
+
+## Global State
+Global state definitions are wrapped in a 'store' which allows for automatic creation and cleanup as needed.
+This API, as well as the underlying hookstate API, can be imported from `@etherealengine/hyperflux`.
+
+```ts title="MyState.ts"
+import { defineState } from '@etherealengine/hyperflux'
+
+const MyState = defineState({
+ name: 'MyState',
+ initial: {
+ count: 0
+ }
+})
+```
+
+Global state will be registered to the engine instance once it has been called with `getState` or `getMutableState`.
+This will cause the state to be created if it does not exist, and will be cleaned up when the engine instance is destroyed.
+
+It's proxy can be accessed with `Engine.instance.store.stateMap.MyState` where `MyState` is the name of the state.
+
+When accessing the state, `getState` returns the underlying object typed as readonly.
+This is useful for reading state values, but should not be used to write to state.
+
+```ts
+import { getState } from '@etherealengine/hyperflux'
+import { MyState } from './MyState'
+
+const state = getState(MyState)
+console.log(state.count) // 0
+state.count = 1 // Error: Cannot assign to 'count' because it is a read-only property.
+```
+
+State can be mutated via the `getMutableState` function, which returns a proxy to the state, which can be used to read and write state values.
+The proxy is reactive, so any changes to the state will cause the component to re-render.
+
+The proxy returned can be wrapped in Hookstate's reactive hook `useHookstate`.
+This will cause the component to re-render when any state values are changed.
+
+```tsx
+import { getMutableState, useHookstate } from '@etherealengine/hyperflux'
+import { MyState } from './MyState'
+
+const MyComponent = () => {
+ const state = useHookstate(getMutableState(MyState))
+ return (
+
+
Count: {state.count}
+
+
+ )
+}
+```
+
diff --git a/docs/developer/typescript/40_reactivity/02_reactors.md b/docs/developer/typescript/40_reactivity/02_reactors.md
new file mode 100644
index 000000000000..63ebc9636e20
--- /dev/null
+++ b/docs/developer/typescript/40_reactivity/02_reactors.md
@@ -0,0 +1 @@
+# Reactors
diff --git a/docs/developer/typescript/40_reactivity/_category_.yml b/docs/developer/typescript/40_reactivity/_category_.yml
new file mode 100644
index 000000000000..c3c5db22d9fc
--- /dev/null
+++ b/docs/developer/typescript/40_reactivity/_category_.yml
@@ -0,0 +1 @@
+position: 40
diff --git a/docs/developer/typescript/40_reactivity/index.md b/docs/developer/typescript/40_reactivity/index.md
new file mode 100644
index 000000000000..457ba766a492
--- /dev/null
+++ b/docs/developer/typescript/40_reactivity/index.md
@@ -0,0 +1,6 @@
+import DocCardList from '@theme/DocCardList'
+
+# Reactivity
+
+
+
diff --git a/docs/developer/typescript/49_networking/_50_networking.md b/docs/developer/typescript/49_networking/_50_networking.md
new file mode 100644
index 000000000000..20a71cd90d21
--- /dev/null
+++ b/docs/developer/typescript/49_networking/_50_networking.md
@@ -0,0 +1,235 @@
+import { TechnicalNote } from '@site/src/components/TechnicalNote';
+import { UnstyledDetails } from '@site/src/components/UnstyledDetails';
+
+# Networking
+We're going to add networking to the `basic` example from the previous section.
+Our goal is to deliver a shared and collaborative experience to many players at once.
+
+## Actions
+First we want to think through what kinds of actions we want in our game.
+For this tutorial we will allow the creation and destruction of simple objects over the network.
+
+In our case we can cheat a bit since destroying objects is common enough that there is a built in world networking event for it, and also for creating objects we can extend the built in world spawning event.
+
+This means that we need to define an action for creation:
+```ts
+const spawnAction = defineAction({
+ ...WorldNetworkAction.spawnObject.actionShape,
+ prefab: 'ee.basic.ball',
+ $topic: NetworkTopics.world
+})
+```
+
+## State
+Ethereal Engine uses an 'event sourced state' paradigm for networking. That means that as a developer you publish an event and that event is performed by all instances simultaneously.
+
+Typically actions are going to affect state. For this example we will declare that we're going to allow any number of objects, each with their own appearance. We define state in a React like way like so:
+
+```ts
+export const BasicState = defineState({
+ name: 'ee.basic.BasicState',
+ initial: {} as Record< EntityUUID, {} >,
+ ...
+```
+
+### Receptors
+Finally for this phase we want to define handlers or receptors to handle the event.
+These are by convention stored on the state itself:
+```ts
+ ...
+ receptors: [
+ [
+ spawnAction,
+ (state, action: typeof spawnAction.matches._TYPE) => {
+ state[action.entityUUID].merge({})
+ }
+ ],
+ [
+ WorldNetworkAction.destroyObject,
+ (state, action: typeof WorldNetworkAction.destroyObject.matches._TYPE) => {
+ state[action.entityUUID].set(none)
+ }
+ ]
+ ]
+```
+
+### Dispatching new events
+We can spawn entities now like so at any time:
+
+```ts
+dispatchAction(spawnAction({ entityUUID:'my-entity' }))
+```
+
+### Rendering State
+
+Once state is being networked we want to visualize that state. The react pattern is to allow state changes to occur and then 'react' to them - creating visual objects that reflect the state database:
+
+```ts
+const ArtifactReactor = ({ entityUUID }: { entityUUID: EntityUUID }) => {
+ const basicState = useHookstate(getMutableState(BasicState)[entityUUID])
+ useEffect(() => {
+ const entity = UUIDComponent.getEntityByUUID(entityUUID)
+ setComponent(entity, TransformComponent)
+ setComponent(entity, VisibleComponent)
+ setComponent(entity, NameComponent,'hello')
+ setComponent(entity, PrimitiveGeometryComponent, { geometryType: 1 })
+```
+
+## Closing
+This example is simple, but these are the building blocks and foundations for creating richer and more complex experiences.
+The source code for this example from https://github.com/etherealengine/ee-tutorial-basic
+
+
+
+
+
+
+
+```ts
+import React, { useEffect } from 'react'
+
+import {
+ defineAction,
+ defineState,
+ dispatchAction,
+ getMutableState,
+ getState,
+ none,
+ useHookstate
+} from '@etherealengine/hyperflux'
+
+import { EntityUUID } from '@etherealengine/common/src/interfaces/EntityUUID'
+
+import { NetworkTopics } from '@etherealengine/spatial/src/networking/classes/Network'
+import { WorldNetworkAction } from '@etherealengine/spatial/src/networking/functions/WorldNetworkAction'
+
+import { isClient } from '@etherealengine/common/src/utils/getEnvironment'
+import { PresentationSystemGroup, defineSystem, getComponent, setComponent } from '@etherealengine/ecs'
+import { ECSState } from '@etherealengine/ecs/src/ECSState'
+import { PrimitiveGeometryComponent } from '@etherealengine/engine/src/scene/components/PrimitiveGeometryComponent'
+import { GeometryTypeEnum } from '@etherealengine/engine/src/scene/constants/GeometryTypeEnum'
+import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
+import { UUIDComponent } from '@etherealengine/spatial/src/common/UUIDComponent'
+import { NetworkState } from '@etherealengine/spatial/src/networking/NetworkState'
+import { ColliderComponent } from '@etherealengine/spatial/src/physics/components/ColliderComponent'
+import { RigidBodyComponent } from '@etherealengine/spatial/src/physics/components/RigidBodyComponent'
+import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
+import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
+import { Vector3 } from 'three'
+
+/**
+ * Basic actions to spawn and destroy objects
+ * This extends and naturally utilizes the functionality in EntityNetworkState
+ */
+
+const BasicActions = {
+ spawnAction: defineAction(
+ WorldNetworkAction.spawnObject.extend({
+ type: 'ee.basic.SPAWN_BALL',
+ $topic: NetworkTopics.world
+ })
+ )
+}
+
+/**
+ * Global state that tracks locally spawned or destroyed artifacts by using action receptors
+ */
+
+const BasicState = defineState({
+ name: 'ee.basic.BasicState',
+
+ initial: {} as Record,
+
+ receptors: {
+ onSpawnAction: BasicActions.spawnAction.receive((action) => {
+ const state = getMutableState(BasicState)
+ state[action.entityUUID].merge({})
+ }),
+ onDestroyObject: WorldNetworkAction.destroyObject.receive((action) => {
+ const state = getMutableState(BasicState)
+ state[action.entityUUID].set(none)
+ })
+ }
+})
+
+/**
+ * A reactor such that each basic state record has an associated a visual artifact
+ */
+
+const ArtifactReactor = ({ entityUUID }: { entityUUID: EntityUUID }) => {
+ /** Entity creation and destruction is handled by EntityNetworkState */
+ const entity = UUIDComponent.useEntityByUUID(entityUUID)
+
+ useEffect(() => {
+ if (!entity) return
+
+ setComponent(entity, TransformComponent, { scale: new Vector3(0.1, 0.1, 0.1) })
+ setComponent(entity, VisibleComponent)
+ setComponent(entity, NameComponent, entityUUID)
+ setComponent(entity, PrimitiveGeometryComponent, { geometryType: GeometryTypeEnum.SphereGeometry })
+ setComponent(entity, RigidBodyComponent, { type: 'dynamic' })
+ setComponent(entity, ColliderComponent, { shape: 'sphere' })
+
+ if (isClient) return
+
+ const angle = Math.random() * Math.PI * 2
+ const direction = new Vector3(Math.sin(angle), 0, Math.cos(angle))
+ const velocity = 0.025 + Math.random() * 0.01
+ getComponent(entity, RigidBodyComponent).body.applyImpulse(direction.multiplyScalar(velocity), true)
+ }, [entity])
+
+ return null
+}
+
+/**
+ * Observe spawn events and create a sub-reactor for each entry in the basic state
+ */
+
+const reactor = () => {
+ const basicState = useHookstate(getMutableState(BasicState))
+ return (
+ <>
+ {basicState.keys.map((entityUUID: EntityUUID) => (
+
+ ))}
+ >
+ )
+}
+
+let counter = 0
+const spawnRate = 3
+
+/**
+ * Spawn a new basic entity every 3 seconds
+ */
+
+const execute = () => {
+ /** Only run this on the server */
+ if (isClient || !NetworkState.worldNetwork) return
+
+ const { deltaSeconds, elapsedSeconds } = getState(ECSState)
+
+ counter += deltaSeconds
+
+ if (counter < spawnRate) return
+ counter = 0
+
+ const entityUUID = `basic-${elapsedSeconds}` as EntityUUID
+ const action = BasicActions.spawnAction({ entityUUID, position: new Vector3(Math.random(), 1, Math.random()) })
+ dispatchAction(action)
+}
+
+/**
+ * System to register the execute function and reactor
+ */
+
+export const BasicSystem = defineSystem({
+ uuid: 'basic.system',
+ reactor,
+ execute,
+ insert: { after: PresentationSystemGroup }
+})
+```
+
+
+
diff --git a/docs/developer/typescript/49_networking/_category_.yml b/docs/developer/typescript/49_networking/_category_.yml
new file mode 100644
index 000000000000..35d19d002bc0
--- /dev/null
+++ b/docs/developer/typescript/49_networking/_category_.yml
@@ -0,0 +1 @@
+position: 49
diff --git a/docs/developer/typescript/49_networking/index.md b/docs/developer/typescript/49_networking/index.md
new file mode 100644
index 000000000000..6484ae461dbf
--- /dev/null
+++ b/docs/developer/typescript/49_networking/index.md
@@ -0,0 +1,15 @@
+---
+sidebar_label: Advanced Networking
+---
+import DocCardList from '@theme/DocCardList'
+
+# Advanced Networking Guide
+
+
diff --git a/docs/developer/typescript/50_avatars/50_IK/_category_.yml b/docs/developer/typescript/50_avatars/50_IK/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_IK/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/50_avatars/50_IK/index.md b/docs/developer/typescript/50_avatars/50_IK/index.md
new file mode 100644
index 000000000000..81c5d41e4354
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_IK/index.md
@@ -0,0 +1,7 @@
+---
+sidebar_label: Inverse Kinematics
+---
+# Inverse Kinematics Guide
+
diff --git a/docs/developer/typescript/50_avatars/50_animations/_category_.yml b/docs/developer/typescript/50_avatars/50_animations/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_animations/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/50_avatars/50_animations/index.md b/docs/developer/typescript/50_avatars/50_animations/index.md
new file mode 100644
index 000000000000..41cfca6f3727
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_animations/index.md
@@ -0,0 +1,7 @@
+---
+sidebar_label: Animations
+---
+# Animations Guide
+
diff --git a/docs/developer/typescript/50_avatars/50_mocap/_category_.yml b/docs/developer/typescript/50_avatars/50_mocap/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_mocap/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/50_avatars/50_mocap/index.md b/docs/developer/typescript/50_avatars/50_mocap/index.md
new file mode 100644
index 000000000000..8fdd2f9497c7
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_mocap/index.md
@@ -0,0 +1,5 @@
+---
+sidebar_label: Motion Capture
+---
+# Motion Capture Guide
+
diff --git a/docs/developer/typescript/50_avatars/50_retargetting/_category_.yml b/docs/developer/typescript/50_avatars/50_retargetting/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_retargetting/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/50_avatars/50_retargetting/index.md b/docs/developer/typescript/50_avatars/50_retargetting/index.md
new file mode 100644
index 000000000000..d187a988175c
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/50_retargetting/index.md
@@ -0,0 +1,7 @@
+---
+sidebar_label: Retargetting
+---
+# Retargetting Guide
+
diff --git a/docs/developer/typescript/50_avatars/_category_.yml b/docs/developer/typescript/50_avatars/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/50_avatars/index.md b/docs/developer/typescript/50_avatars/index.md
new file mode 100644
index 000000000000..6b1de3bd1c44
--- /dev/null
+++ b/docs/developer/typescript/50_avatars/index.md
@@ -0,0 +1,11 @@
+---
+sidebar_label: Avatars
+---
+import DocCardList from '@theme/DocCardList'
+
+# Avatars Guide
+
+
+
diff --git a/docs/developer/typescript/60_mastery/49_engineCode/01_api.md b/docs/developer/typescript/60_mastery/49_engineCode/01_api.md
new file mode 100644
index 000000000000..8d577b12a974
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/49_engineCode/01_api.md
@@ -0,0 +1 @@
+# Reference API
diff --git a/docs/developer/typescript/60_mastery/49_engineCode/02_modules/_category_.yml b/docs/developer/typescript/60_mastery/49_engineCode/02_modules/_category_.yml
new file mode 100644
index 000000000000..e34d8cd3b323
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/49_engineCode/02_modules/_category_.yml
@@ -0,0 +1 @@
+position: 02
diff --git a/docs/developer/typescript/60_mastery/49_engineCode/02_modules/index.md b/docs/developer/typescript/60_mastery/49_engineCode/02_modules/index.md
new file mode 100644
index 000000000000..45ad0bb27838
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/49_engineCode/02_modules/index.md
@@ -0,0 +1,13 @@
+import DocCardList from '@theme/DocCardList';
+
+# Engine Modules Guide
+
+
diff --git a/docs/developer/typescript/60_mastery/49_engineCode/_category_.yml b/docs/developer/typescript/60_mastery/49_engineCode/_category_.yml
new file mode 100644
index 000000000000..35d19d002bc0
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/49_engineCode/_category_.yml
@@ -0,0 +1 @@
+position: 49
diff --git a/docs/developer/typescript/60_mastery/49_engineCode/index.md b/docs/developer/typescript/60_mastery/49_engineCode/index.md
new file mode 100644
index 000000000000..6a458c7b8de2
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/49_engineCode/index.md
@@ -0,0 +1,8 @@
+import DocCardList from '@theme/DocCardList';
+
+# Engine Code Navigation
+
+
+
diff --git a/docs/developer/typescript/60_mastery/50_cms/_category_.yml b/docs/developer/typescript/60_mastery/50_cms/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/50_cms/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/60_mastery/50_cms/index.md b/docs/developer/typescript/60_mastery/50_cms/index.md
new file mode 100644
index 000000000000..24fd225b5888
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/50_cms/index.md
@@ -0,0 +1,10 @@
+---
+sidebar_label: CMS
+---
+# CMS Guide
+
+## Projects
+## Assets
diff --git a/docs/developer/typescript/60_mastery/50_gltf/_category_.yml b/docs/developer/typescript/60_mastery/50_gltf/_category_.yml
new file mode 100644
index 000000000000..222dfff00c2f
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/50_gltf/_category_.yml
@@ -0,0 +1 @@
+position: 50
diff --git a/docs/developer/typescript/60_mastery/50_gltf/index.md b/docs/developer/typescript/60_mastery/50_gltf/index.md
new file mode 100644
index 000000000000..292a8e1c6db0
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/50_gltf/index.md
@@ -0,0 +1,8 @@
+---
+sidebar_label: glTF
+---
+# glTF Guide
+
diff --git a/docs/developer/typescript/60_mastery/51_rendering/_category_.yml b/docs/developer/typescript/60_mastery/51_rendering/_category_.yml
new file mode 100644
index 000000000000..4966be4313e4
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/51_rendering/_category_.yml
@@ -0,0 +1 @@
+position: 51
diff --git a/docs/developer/typescript/60_mastery/51_rendering/index.md b/docs/developer/typescript/60_mastery/51_rendering/index.md
new file mode 100644
index 000000000000..6126ef56116a
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/51_rendering/index.md
@@ -0,0 +1,11 @@
+---
+sidebar_label: Rendering
+---
+# Rendering Guide
+
diff --git a/docs/developer/typescript/60_mastery/60_cicd/_category_.yml b/docs/developer/typescript/60_mastery/60_cicd/_category_.yml
new file mode 100644
index 000000000000..4966be4313e4
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/60_cicd/_category_.yml
@@ -0,0 +1 @@
+position: 51
diff --git a/docs/developer/typescript/60_mastery/60_cicd/index.md b/docs/developer/typescript/60_mastery/60_cicd/index.md
new file mode 100644
index 000000000000..c68305f4f80f
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/60_cicd/index.md
@@ -0,0 +1,5 @@
+# CI/CD
+
+
diff --git a/docs/manual/03_modules/01_engine/07_testing/01_reasonableCode.md b/docs/developer/typescript/60_mastery/60_testing/01_reasonableCode.md
similarity index 100%
rename from docs/manual/03_modules/01_engine/07_testing/01_reasonableCode.md
rename to docs/developer/typescript/60_mastery/60_testing/01_reasonableCode.md
diff --git a/docs/manual/03_modules/01_engine/07_testing/02_testDrivenDevelopment.md b/docs/developer/typescript/60_mastery/60_testing/02_testDrivenDevelopment.md
similarity index 100%
rename from docs/manual/03_modules/01_engine/07_testing/02_testDrivenDevelopment.md
rename to docs/developer/typescript/60_mastery/60_testing/02_testDrivenDevelopment.md
diff --git a/docs/developer/typescript/60_mastery/60_testing/_category_.yml b/docs/developer/typescript/60_mastery/60_testing/_category_.yml
new file mode 100644
index 000000000000..0c02fd033a91
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/60_testing/_category_.yml
@@ -0,0 +1 @@
+position: 60
diff --git a/docs/manual/03_modules/01_engine/07_testing/index.md b/docs/developer/typescript/60_mastery/60_testing/index.md
similarity index 100%
rename from docs/manual/03_modules/01_engine/07_testing/index.md
rename to docs/developer/typescript/60_mastery/60_testing/index.md
diff --git a/docs/developer/typescript/60_mastery/_category_.yml b/docs/developer/typescript/60_mastery/_category_.yml
new file mode 100644
index 000000000000..0c02fd033a91
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/_category_.yml
@@ -0,0 +1 @@
+position: 60
diff --git a/docs/developer/typescript/60_mastery/index.md b/docs/developer/typescript/60_mastery/index.md
new file mode 100644
index 000000000000..b32df996a534
--- /dev/null
+++ b/docs/developer/typescript/60_mastery/index.md
@@ -0,0 +1,11 @@
+import DocCardList from '@theme/DocCardList';
+
+# Mastery Toolkit
+
+
+
diff --git a/docs/developer/typescript/typescript.md b/docs/developer/typescript/typescript.md
index 187ca418e07c..ce702b4eda45 100644
--- a/docs/developer/typescript/typescript.md
+++ b/docs/developer/typescript/typescript.md
@@ -2,22 +2,16 @@
sidebar_position: 00
---
# Become a Developer
-
-This section will explain everything that there is to know about programming with Ethereal Engine.
-
-_This page will contain an Introduction to the Developer Learning Site._
-_In the meantime, please refer to the [Manual](/manual) section for more information._
-
-# Introduction
+Here you will learn everything that there is to know about programming with Typescript + Ethereal Engine.
-_This page will contain an introduction to the Getting Started: Developer guides._
+ No-Code: Segue into the VisualScript Learning site
+ Typescript: Segue into the Typescript Learning Site (this site)
_Programming in Ethereal Engine can be done through **Typescript**._
_But the engine also has a visual alternative to programming, called **VisualScript**._
-
+-->
diff --git a/docs/manual/03_modules/01_engine/03_stateManagement.md b/docs/manual/03_modules/01_engine/03_stateManagement.md
index 0c5077f113fe..8e423ecc51e7 100644
--- a/docs/manual/03_modules/01_engine/03_stateManagement.md
+++ b/docs/manual/03_modules/01_engine/03_stateManagement.md
@@ -1,79 +1,6 @@
# State Management
-
-All of Ethereal Engine's state management uses [Hookstate](https://hookstate.js.org/) and [React](https://react.dev/).
-Together, these tools give reactive, declarative, and controlled state management across any scope.
-
-## Scoped State
-Scoped state can be defined using the `useHookstate` hook.
-This functionality uses vanilla `Hookstate`, and is useful for:
-- State that is only used in a single component
-- State that is only used in a single component tree
-
-```tsx
-import { useHookstate } from '@hookstate/core'
-
-const MyComponent = () => {
- const state = useHookstate({
- count: 0
- })
- return (
-
-
Count: {state.count}
-
-
- )
-}
-```
-
-## Global State
-Global state definitions are wrapped in a 'store' which allows for automatic creation and cleanup as needed.
-This API, as well as the underlying hookstate API, can be imported from `@etherealengine/hyperflux`.
-
-```ts title="MyState.ts"
-import { defineState } from '@etherealengine/hyperflux'
-
-const MyState = defineState({
- name: 'MyState',
- initial: {
- count: 0
- }
-})
-```
-
-Global state will be registered to the engine instance once it has been called with `getState` or `getMutableState`.
-This will cause the state to be created if it does not exist, and will be cleaned up when the engine instance is destroyed.
-
-It's proxy can be accessed with `Engine.instance.store.stateMap.MyState` where `MyState` is the name of the state.
-
-When accessing the state, `getState` returns the underlying object typed as readonly.
-This is useful for reading state values, but should not be used to write to state.
-
-```ts
-import { getState } from '@etherealengine/hyperflux'
-import { MyState } from './MyState'
-
-const state = getState(MyState)
-console.log(state.count) // 0
-state.count = 1 // Error: Cannot assign to 'count' because it is a read-only property.
-```
-
-State can be mutated via the `getMutableState` function, which returns a proxy to the state, which can be used to read and write state values.
-The proxy is reactive, so any changes to the state will cause the component to re-render.
-
-The proxy returned can be wrapped in Hookstate's reactive hook `useHookstate`.
-This will cause the component to re-render when any state values are changed.
-
-```tsx
-import { getMutableState, useHookstate } from '@etherealengine/hyperflux'
-import { MyState } from './MyState'
-
-const MyComponent = () => {
- const state = useHookstate(getMutableState(MyState))
- return (
-
-
Count: {state.count}
-
-
- )
-}
-```
+
diff --git a/docs/manual/03_modules/01_engine/04_ecs.md b/docs/manual/03_modules/01_engine/04_ecs.md
index 6ea1fc9541e2..39145d5b208a 100644
--- a/docs/manual/03_modules/01_engine/04_ecs.md
+++ b/docs/manual/03_modules/01_engine/04_ecs.md
@@ -10,7 +10,21 @@ ECS refers to the "**Entity Component System**" architecture paradigm, that is c
They allow data to be structured with composition instead of inheritance.
- **Systems** are functions that operate on these entities and components.
-## Component Definitions
+
+
+## Component Data Types
Components support two types of data:
- Structure of Arrays
- Array of Structures
@@ -60,81 +74,6 @@ const DebugArrowComponent = defineComponent({
})
```
-### onInit
-`(entity: Entity) => ComponentType`
-**onInit** is a function that is called when **setComponent** is called on an entity that does not have the component in question.
-It takes an entity number, and should return an object with the initial values for the component.
-
-
-### onSet
-`entity: Entity, component: ComponentType, json: SerializedComponentType) => void`
-**onSet** is a function that is called each time **setComponent** is called.
-It takes an `entity` number, a `component` object and a `json` object.
-
-This function provides a method for reactive data to be updated in batch _(such as deserializing scene data)_, which allows for a much tighter data flow.
-
-
-### onRemove
-`(entity: Entity, component: ComponentType) => void`
-**onRemove** is a function that is called when **removeComponent** is called on an entity that has the component in question.
-It takes an `entity` number and a `component` object.
-
-This function is where any resources associated with the component should be cleaned.
-
-
-### toJSON
-`(entity: Entity, component: ComponentType) => SerializedComponentType`
-**toJSON** is a function that is called when **serializeComponent** is called on an entity that has the component in question.
-It takes an entity number and a component object.
-
-This function is where the component's data should be serialized _(eg: transforming a scene's data for saving to a file)_.
-
-### jsonID
-`string`
-The **jsonID** property is a string that is used to identify the component in json.
-
-It is used for identifying scenes when their data is serialized/deserialized.
-
-### reactor
-`function(props: { root: EntityRoot }) => void`
-The **reactor** property specifies a function that exists for the duration of this component instance.
-
-This function is where any effects that depend on the component should be defined.
-
-
-## Update Loop
-Ethereal Engine uses a very similar model to [Unity's update loop](https://docs.unity3d.com/Manual/ExecutionOrder.html), by the use of a [fixed timestep](https://www.gafferongames.com/post/fix_your_timestep/) update loop.
-
-The engine defines a `frame update` process that is called once per frame.
-Inside this frame-update process there is a `fixed update` process that operates with an `accumulator` pattern.
-This accumulator ensures that time will always step at a stable number of updates per second, independent of the processing power of the hardware running the engine.
-
-_Note: Because the fixed update process is independent of frame updates, each individual frame update may execute 0-to-many fixed updates during its lifetime._
-
-Ethereal Engine implements this feature through system **pipelines**, which are collections of systems that will be executed in a specific order.
-
-## Queries
-Queries are used to select entities that have a specific set of components.
-They are used to define the entities that a system will operate on.
-
-Queries are defined using the **defineQuery** function:
-```ts
-const query = defineQuery([TransformComponent, GroupComponent])
-
-const entities = query() // returns an array of entity numbers
-```
-
-Queries also have enter and exit derivatives.
-They are used to define when a combination of components is added or removed from an entity.
-These variations are defined using the **defineEnterQuery** and **defineExitQuery** functions:
-```ts
-const query = defineQuery([TransformComponent, GroupComponent])
-
-const allEntities = query()
-const enterEntities = query.enter()
-const exitEntities = query.exit()
-```
-
## Examples
diff --git a/docs/manual/03_modules/01_engine/07_testing/_category_.yml b/docs/manual/03_modules/01_engine/07_testing/_category_.yml
deleted file mode 100644
index afad33bf7b1a..000000000000
--- a/docs/manual/03_modules/01_engine/07_testing/_category_.yml
+++ /dev/null
@@ -1 +0,0 @@
-position: 7
\ No newline at end of file
diff --git a/src/components/TechnicalNote.tsx b/src/components/TechnicalNote.tsx
new file mode 100644
index 000000000000..cf4b4ddaa976
--- /dev/null
+++ b/src/components/TechnicalNote.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+const DetailsCSS = "details_node_modules-@docusaurus-theme-common-lib-components-Details-styles-module isBrowser_node_modules-@docusaurus-theme-common-lib-components-Details-styles-module alert alert--info details_node_modules-@docusaurus-theme-classic-lib-theme-Details-styles-module "
+
+export const TechnicalNote = (props) => {
+ const TextTitle = props.title ? props.title : "Technical Note"
+ const Note = "alert alert--secondary mb-5 bg-neutral-900"
+ //const Note = DetailsCSS + "mb-5 bg-neutral-900"
+ const Title = "text-blue-200"
+ const Body = "pt-4"
+ return (
+
+ {TextTitle}
+