diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000..fab2a6a
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,47 @@
+# Checks the site on every pull request and after every docs-sync push to main (the synced folders arrive without a PR).
+name: Tests
+
+on:
+ pull_request:
+ branches:
+ - main
+ push:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ tests:
+ name: Validate the site
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6
+ with:
+ persist-credentials: false
+
+ - name: Set up Node
+ uses: actions/setup-node@v6
+ with:
+ node-version-file: .nvmrc
+
+ - name: Install dependencies
+ run: |
+ npm install -g "$(node -p 'require("./package.json").packageManager')"
+ pnpm install --frozen-lockfile
+
+ - name: Lint
+ run: pnpm run lint
+
+ # docs.json $refs, missing pages, invalid MDX and imports
+ - name: Validate the build
+ run: pnpm run validate
+
+ - name: Check the links
+ run: pnpm run broken-links
+
+ - name: Check accessibility
+ run: pnpm run a11y
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..40606b6
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,7 @@
+# Owned by the source repositories, written by the docs-sync action at their releases.
+docs/
+guides/
+references/
+pnpm-lock.yaml
+# Written by pnpm.
+pnpm-workspace.yaml
diff --git a/README.md b/README.md
index eb0d970..d4b2078 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,33 @@
-
+
# NanoForge Documentation
-Welcome to the official documentation for NanoForge, your go-to tool for building and managing ECS-based applications with ease. This documentation provides comprehensive guides, tutorials, and reference materials to help you get started and make the most out of NanoForge.
+The NanoForge documentation site, built with [Mintlify](https://mintlify.com): https://docs.nanoforge.eu
-https://docs.nanoforge.eu
+## How the site is made
+Each product's pages live in its own repository and reach this one through the `docs-sync` action of [NanoForge-dev/actions](https://github.com/NanoForge-dev/actions), at each release of that repository:
+
+| Folder | Written by | Source |
+| ---------------------------------- | --------------- | ----------------------------------------------------- |
+| `docs/engine`, `references/engine` | engine releases | `docs/docs`, the TypeDoc references (`pnpm run docs`) |
+| `docs/cli`, `guides/cli` | cli releases | `docs/docs`, `docs/guides` |
+| `docs/loader` | loader releases | `docs/docs` |
+| `docs/editor` | editor releases | `docs/docs` |
+
+- **Don't edit those folders here:** the next sync deletes and rewrites them. Change the pages in their repository.
+- Each synced folder holds a `navigation.json`, written from the source repository's own one. It sets the order and the groups of its pages.
+- `references//navigation.json` lists the reference versions: the latest release of each major.
+- This repository owns `docs.json` (theme, tabs, dropdowns, redirects), `index.mdx` and `custom.css`. `docs.json` includes each `navigation.json` with a `$ref`, so a new product is one entry there.
+
+## Commands
+
+Mintlify needs Node 24 (`.nvmrc`); it refuses Node 25+.
+
+```sh
+pnpm dev # preview on port 3001
+pnpm validate # docs.json, $refs, missing pages, MDX
+pnpm broken-links
+pnpm a11y
+pnpm lint
+```
diff --git a/docs.json b/docs.json
index 90b89d8..020f4da 100644
--- a/docs.json
+++ b/docs.json
@@ -3,9 +3,7 @@
"theme": "almond",
"name": "NanoForge",
"custom": {
- "css": [
- "custom.css"
- ]
+ "css": ["custom.css"]
},
"colors": {
"primary": "#4923b6",
@@ -13,2690 +11,265 @@
"dark": "#7c3aed"
},
"navigation": {
- "languages": [
+ "tabs": [
{
- "language": "en",
- "tabs": [
+ "tab": "Documentation",
+ "dropdowns": [
{
- "tab": "Documentation",
- "dropdowns": [
- {
- "dropdown": "Engine",
- "groups": [
- {
- "group": "Getting-Started",
- "pages": [
- "docs/engine/getting-started/1-index",
- "docs/engine/getting-started/documentation",
- "docs/engine/getting-started/how_to_use"
- ]
- },
- {
- "group": "Network",
- "pages": [
- "docs/engine/network/index",
- "docs/engine/network/network-client-api",
- "docs/engine/network/network-client",
- "docs/engine/network/network-server-api",
- "docs/engine/network/network-server",
- "docs/engine/network/packet-framing"
- ]
- },
- {
- "group": "Registry",
- "pages": [
- "docs/engine/registry/index",
- "docs/engine/registry/writing_web_assembly"
- ]
- }
- ]
- },
- {
- "dropdown": "CLI",
- "groups": [
- {
- "group": "Commands",
- "pages": [
- "docs/cli/commands/1-overview",
- {
- "group": "Commands",
- "pages": [
- "docs/cli/commands/2-commands/1-new",
- "docs/cli/commands/2-commands/2-dev",
- "docs/cli/commands/2-commands/3-build",
- "docs/cli/commands/2-commands/4-start",
- "docs/cli/commands/2-commands/5-create",
- "docs/cli/commands/2-commands/6-install",
- "docs/cli/commands/2-commands/7-install",
- "docs/cli/commands/2-commands/7-editor",
- "docs/cli/commands/2-commands/8-editor",
- "docs/cli/commands/2-commands/8-registry",
- "docs/cli/commands/2-commands/9-registry"
- ]
- }
- ]
- },
- {
- "group": "Configuration",
- "pages": [
- "docs/cli/configuration/1-configuration-file",
- "docs/cli/configuration/2-environment-variables"
- ]
- },
- {
- "group": "Getting-Started",
- "pages": [
- "docs/cli/getting-started/1-introduction",
- "docs/cli/getting-started/2-installation",
- "docs/cli/getting-started/3-quickstart",
- "docs/cli/getting-started/index",
- "docs/cli/getting-started/usage"
- ]
- },
- {
- "group": "Loader",
- "pages": [
- "docs/cli/loader/1-overview",
- "docs/cli/loader/2-client",
- "docs/cli/loader/3-website",
- "docs/cli/loader/4-server"
- ]
- },
- {
- "group": "Schematics",
- "pages": [
- "docs/cli/schematics/1-overview",
- {
- "group": "Schematics",
- "pages": [
- "docs/cli/schematics/2-schematics/1-application",
- "docs/cli/schematics/2-schematics/1-workspace",
- "docs/cli/schematics/2-schematics/2-configuration",
- "docs/cli/schematics/2-schematics/2-project",
- "docs/cli/schematics/2-schematics/3-component",
- "docs/cli/schematics/2-schematics/3-part-base",
- "docs/cli/schematics/2-schematics/4-system",
- "docs/cli/schematics/2-schematics/4-part-main",
- "docs/cli/schematics/2-schematics/5-docker",
- "docs/cli/schematics/2-schematics/6-component",
- "docs/cli/schematics/2-schematics/7-system"
- ]
- }
- ]
- }
- ]
- }
- ]
+ "dropdown": "Overview",
+ "icon": "house",
+ "pages": ["index"]
},
{
- "tab": "Guides",
- "dropdowns": [
- {
- "dropdown": "CLI",
- "groups": [
- {
- "group": "CLI",
- "pages": [
- "guides/cli/cli/1-overview",
- "guides/cli/cli/2-create-a-project",
- "guides/cli/cli/3-develop-locally",
- "guides/cli/cli/4-build-and-deploy",
- "guides/cli/cli/5-components-and-systems",
- "guides/cli/cli/6-publish-a-package"
- ]
- }
- ]
- }
- ]
+ "dropdown": "Engine",
+ "icon": "gears",
+ "pages": {
+ "$ref": "./docs/engine/navigation.json"
+ }
},
{
- "tab": "References",
- "versions": [
- {
- "version": "1.4.0",
- "dropdowns": [
- {
- "dropdown": "Asset-Manager",
- "pages": [
- "references/1.4.0/asset-manager/0-index",
- {
- "group": "AssetManagerLibrary",
- "pages": [
- "references/1.4.0/asset-manager/AssetManagerLibrary/getAsset_1",
- "references/1.4.0/asset-manager/AssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.0/asset-manager/AssetManagerLibrary"
- }
- ]
- },
- {
- "dropdown": "Common",
- "pages": [
- "references/1.4.0/common/0-index",
- {
- "group": "ApplicationContext",
- "pages": [
- "references/1.4.0/common/ApplicationContext/delta",
- "references/1.4.0/common/ApplicationContext/isRunning"
- ],
- "root": "references/1.4.0/common/ApplicationContext"
- },
- "references/1.4.0/common/ASSET_MANAGER_LIBRARY",
- {
- "group": "BaseAssetManagerLibrary",
- "pages": [
- "references/1.4.0/common/BaseAssetManagerLibrary/getAsset_1",
- "references/1.4.0/common/BaseAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.0/common/BaseAssetManagerLibrary"
- },
- "references/1.4.0/common/BaseComponentSystemLibrary",
- "references/1.4.0/common/BaseGraphicsLibrary",
- "references/1.4.0/common/BaseInputLibrary",
- {
- "group": "BaseMusicLibrary",
- "pages": [
- "references/1.4.0/common/BaseMusicLibrary/mute",
- "references/1.4.0/common/BaseMusicLibrary/play"
- ],
- "root": "references/1.4.0/common/BaseMusicLibrary"
- },
- "references/1.4.0/common/BaseNetworkLibrary",
- {
- "group": "BaseSoundLibrary",
- "pages": [
- "references/1.4.0/common/BaseSoundLibrary/mute",
- "references/1.4.0/common/BaseSoundLibrary/play"
- ],
- "root": "references/1.4.0/common/BaseSoundLibrary"
- },
- "references/1.4.0/common/ClearContext",
- {
- "group": "ClientLibraryManager",
- "pages": [
- "references/1.4.0/common/ClientLibraryManager/constructor",
- "references/1.4.0/common/ClientLibraryManager/get",
- "references/1.4.0/common/ClientLibraryManager/getAssetManager",
- "references/1.4.0/common/ClientLibraryManager/getComponentSystem",
- "references/1.4.0/common/ClientLibraryManager/getGraphics",
- "references/1.4.0/common/ClientLibraryManager/getInput",
- "references/1.4.0/common/ClientLibraryManager/getMusic",
- "references/1.4.0/common/ClientLibraryManager/getNetwork",
- "references/1.4.0/common/ClientLibraryManager/getSound"
- ],
- "root": "references/1.4.0/common/ClientLibraryManager"
- },
- "references/1.4.0/common/COMPONENT_SYSTEM_LIBRARY",
- {
- "group": "Context",
- "pages": [
- "references/1.4.0/common/Context/app",
- "references/1.4.0/common/Context/constructor",
- "references/1.4.0/common/Context/libs"
- ],
- "root": "references/1.4.0/common/Context"
- },
- "references/1.4.0/common/DefaultLibrariesEnum",
- "references/1.4.0/common/ExecutionContext",
- "references/1.4.0/common/GRAPHICS_LIBRARY",
- {
- "group": "IAssetManagerLibrary",
- "pages": [
- "references/1.4.0/common/IAssetManagerLibrary/getAsset_1",
- "references/1.4.0/common/IAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.0/common/IAssetManagerLibrary"
- },
- "references/1.4.0/common/IComponentSystemLibrary",
- {
- "group": "IConfigRegistry",
- "pages": [
- "references/1.4.0/common/IConfigRegistry/registerConfig"
- ],
- "root": "references/1.4.0/common/IConfigRegistry"
- },
- "references/1.4.0/common/IExposedLibrary",
- "references/1.4.0/common/IGraphicsLibrary",
- "references/1.4.0/common/IInputLibrary",
- "references/1.4.0/common/ILibrary",
- "references/1.4.0/common/IMusicLibrary",
- {
- "group": "IMutableLibrary",
- "pages": [
- "references/1.4.0/common/IMutableLibrary/mute"
- ],
- "root": "references/1.4.0/common/IMutableLibrary"
- },
- "references/1.4.0/common/INetworkLibrary",
- {
- "group": "InitContext",
- "pages": [
- "references/1.4.0/common/InitContext/config",
- "references/1.4.0/common/InitContext/constructor",
- "references/1.4.0/common/InitContext/container",
- "references/1.4.0/common/InitContext/env",
- "references/1.4.0/common/InitContext/files"
- ],
- "root": "references/1.4.0/common/InitContext"
- },
- "references/1.4.0/common/INPUT_LIBRARY",
- {
- "group": "IRunClientOptions",
- "pages": [
- "references/1.4.0/common/IRunClientOptions/container",
- "references/1.4.0/common/IRunClientOptions/env",
- "references/1.4.0/common/IRunClientOptions/files"
- ],
- "root": "references/1.4.0/common/IRunClientOptions"
- },
- "references/1.4.0/common/IRunnerLibrary",
- "references/1.4.0/common/IRunOptions",
- {
- "group": "IRunServerOptions",
- "pages": [
- "references/1.4.0/common/IRunServerOptions/env",
- "references/1.4.0/common/IRunServerOptions/files"
- ],
- "root": "references/1.4.0/common/IRunServerOptions"
- },
- "references/1.4.0/common/ISoundLibrary",
- {
- "group": "Library",
- "pages": [
- "references/1.4.0/common/Library/_relationship",
- "references/1.4.0/common/Library/constructor"
- ],
- "root": "references/1.4.0/common/Library"
- },
- {
- "group": "LibraryContext",
- "pages": [
- "references/1.4.0/common/LibraryContext/status"
- ],
- "root": "references/1.4.0/common/LibraryContext"
- },
- {
- "group": "LibraryHandle",
- "pages": [
- "references/1.4.0/common/LibraryHandle/constructor",
- "references/1.4.0/common/LibraryHandle/context",
- "references/1.4.0/common/LibraryHandle/library",
- "references/1.4.0/common/LibraryHandle/symbol"
- ],
- "root": "references/1.4.0/common/LibraryHandle"
- },
- {
- "group": "LibraryManager",
- "pages": [
- "references/1.4.0/common/LibraryManager/constructor",
- "references/1.4.0/common/LibraryManager/getAssetManager",
- "references/1.4.0/common/LibraryManager/getComponentSystem",
- "references/1.4.0/common/LibraryManager/getGraphics",
- "references/1.4.0/common/LibraryManager/getInput",
- "references/1.4.0/common/LibraryManager/getMusic",
- "references/1.4.0/common/LibraryManager/getNetwork",
- "references/1.4.0/common/LibraryManager/getSound"
- ],
- "root": "references/1.4.0/common/LibraryManager"
- },
- "references/1.4.0/common/LibraryStatusEnum",
- "references/1.4.0/common/MUSIC_LIBRARY",
- "references/1.4.0/common/NETWORK_LIBRARY",
- {
- "group": "NfConfigException",
- "pages": [
- "references/1.4.0/common/NfConfigException/code",
- "references/1.4.0/common/NfConfigException/constructor"
- ],
- "root": "references/1.4.0/common/NfConfigException"
- },
- {
- "group": "NfFetchException",
- "pages": [
- "references/1.4.0/common/NfFetchException/code",
- "references/1.4.0/common/NfFetchException/constructor"
- ],
- "root": "references/1.4.0/common/NfFetchException"
- },
- {
- "group": "NfFile",
- "pages": [
- "references/1.4.0/common/NfFile/arrayBuffer",
- "references/1.4.0/common/NfFile/blob",
- "references/1.4.0/common/NfFile/bytes",
- "references/1.4.0/common/NfFile/constructor",
- "references/1.4.0/common/NfFile/formData",
- "references/1.4.0/common/NfFile/json",
- "references/1.4.0/common/NfFile/path",
- "references/1.4.0/common/NfFile/text"
- ],
- "root": "references/1.4.0/common/NfFile"
- },
- {
- "group": "NfNotFound",
- "pages": [
- "references/1.4.0/common/NfNotFound/code",
- "references/1.4.0/common/NfNotFound/constructor"
- ],
- "root": "references/1.4.0/common/NfNotFound"
- },
- {
- "group": "NfNotInitializedException",
- "pages": [
- "references/1.4.0/common/NfNotInitializedException/code",
- "references/1.4.0/common/NfNotInitializedException/constructor"
- ],
- "root": "references/1.4.0/common/NfNotInitializedException"
- },
- "references/1.4.0/common/SOUND_LIBRARY"
- ]
- },
- {
- "dropdown": "Config",
- "pages": [
- "references/1.4.0/config/0-index",
- "references/1.4.0/config/Default",
- "references/1.4.0/config/IsIpOrFQDN",
- "references/1.4.0/config/TransformToBoolean"
- ]
- },
- {
- "dropdown": "Core",
- "pages": [
- "references/1.4.0/core/0-index",
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.4.0/core/NanoforgeClient/useGraphics",
- "references/1.4.0/core/NanoforgeClient/useInput",
- "references/1.4.0/core/NanoforgeClient/useSound"
- ],
- "root": "references/1.4.0/core/NanoforgeClient"
- },
- "references/1.4.0/core/NanoforgeFactory",
- "references/1.4.0/core/NanoforgeServer"
- ]
- },
- {
- "dropdown": "Core-Editor",
- "pages": [
- "references/1.4.0/core-editor/0-index",
- "references/1.4.0/core-editor/CoreEvents",
- "references/1.4.0/core-editor/EditorEvents",
- {
- "group": "EventEmitter",
- "pages": [
- "references/1.4.0/core-editor/EventEmitter/constructor",
- "references/1.4.0/core-editor/EventEmitter/emit",
- "references/1.4.0/core-editor/EventEmitter/on",
- "references/1.4.0/core-editor/EventEmitter/runEvents"
- ],
- "root": "references/1.4.0/core-editor/EventEmitter"
- },
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.4.0/core-editor/NanoforgeClient/useGraphics",
- "references/1.4.0/core-editor/NanoforgeClient/useInput",
- "references/1.4.0/core-editor/NanoforgeClient/useSound"
- ],
- "root": "references/1.4.0/core-editor/NanoforgeClient"
- },
- "references/1.4.0/core-editor/NanoforgeFactory",
- "references/1.4.0/core-editor/NanoforgeServer"
- ]
- },
- {
- "dropdown": "ECS-Client",
- "pages": [
- "references/1.4.0/ecs-client/0-index",
- {
- "group": "ECSClientLibrary",
- "pages": [
- "references/1.4.0/ecs-client/ECSClientLibrary/constructor"
- ],
- "root": "references/1.4.0/ecs-client/ECSClientLibrary"
- }
- ]
- },
- {
- "dropdown": "ECS-Lib",
- "pages": [
- "references/1.4.0/ecs-lib/0-index",
- {
- "group": "AbstractECSLibrary",
- "pages": [
- "references/1.4.0/ecs-lib/AbstractECSLibrary/_registry",
- "references/1.4.0/ecs-lib/AbstractECSLibrary/constructor",
- "references/1.4.0/ecs-lib/AbstractECSLibrary/module",
- "references/1.4.0/ecs-lib/AbstractECSLibrary/path",
- "references/1.4.0/ecs-lib/AbstractECSLibrary/registry"
- ],
- "root": "references/1.4.0/ecs-lib/AbstractECSLibrary"
- },
- "references/1.4.0/ecs-lib/Component",
- "references/1.4.0/ecs-lib/EditorComponentManifest",
- "references/1.4.0/ecs-lib/EditorSystemManifest",
- {
- "group": "Entity",
- "pages": [
- "references/1.4.0/ecs-lib/Entity/getId"
- ],
- "root": "references/1.4.0/ecs-lib/Entity"
- },
- {
- "group": "Registry",
- "pages": [
- "references/1.4.0/ecs-lib/Registry/addComponent",
- "references/1.4.0/ecs-lib/Registry/addSystem",
- "references/1.4.0/ecs-lib/Registry/clearEntities",
- "references/1.4.0/ecs-lib/Registry/clearSystems",
- "references/1.4.0/ecs-lib/Registry/entityFromIndex",
- "references/1.4.0/ecs-lib/Registry/getComponents",
- "references/1.4.0/ecs-lib/Registry/getComponentsConst",
- "references/1.4.0/ecs-lib/Registry/getEntityComponent",
- "references/1.4.0/ecs-lib/Registry/getEntityComponentConst",
- "references/1.4.0/ecs-lib/Registry/getIndexedZipper",
- "references/1.4.0/ecs-lib/Registry/getZipper",
- "references/1.4.0/ecs-lib/Registry/killEntity",
- "references/1.4.0/ecs-lib/Registry/maxEntities",
- "references/1.4.0/ecs-lib/Registry/registerComponent",
- "references/1.4.0/ecs-lib/Registry/removeComponent",
- "references/1.4.0/ecs-lib/Registry/removeSystem",
- "references/1.4.0/ecs-lib/Registry/runSystems",
- "references/1.4.0/ecs-lib/Registry/spawnEntity"
- ],
- "root": "references/1.4.0/ecs-lib/Registry"
- },
- {
- "group": "SparseArray",
- "pages": [
- "references/1.4.0/ecs-lib/SparseArray/clear",
- "references/1.4.0/ecs-lib/SparseArray/empty",
- "references/1.4.0/ecs-lib/SparseArray/erase",
- "references/1.4.0/ecs-lib/SparseArray/get",
- "references/1.4.0/ecs-lib/SparseArray/getConst",
- "references/1.4.0/ecs-lib/SparseArray/getIndex",
- "references/1.4.0/ecs-lib/SparseArray/insertAt_1",
- "references/1.4.0/ecs-lib/SparseArray/insertAt",
- "references/1.4.0/ecs-lib/SparseArray/resize",
- "references/1.4.0/ecs-lib/SparseArray/set",
- "references/1.4.0/ecs-lib/SparseArray/setByCopy",
- "references/1.4.0/ecs-lib/SparseArray/setByMove",
- "references/1.4.0/ecs-lib/SparseArray/size"
- ],
- "root": "references/1.4.0/ecs-lib/SparseArray"
- },
- "references/1.4.0/ecs-lib/System"
- ]
- },
- {
- "dropdown": "ECS-Server",
- "pages": [
- "references/1.4.0/ecs-server/0-index",
- {
- "group": "ECSServerLibrary",
- "pages": [
- "references/1.4.0/ecs-server/ECSServerLibrary/constructor"
- ],
- "root": "references/1.4.0/ecs-server/ECSServerLibrary"
- },
- "references/1.4.0/ecs-server/Module"
- ]
- },
- {
- "dropdown": "Graphics-2d",
- "pages": [
- "references/1.4.0/graphics-2d/0-index",
- "references/1.4.0/graphics-2d/Animation_2",
- "references/1.4.0/graphics-2d/Arc",
- "references/1.4.0/graphics-2d/ArcConfig",
- "references/1.4.0/graphics-2d/Arrow",
- "references/1.4.0/graphics-2d/ArrowConfig",
- "references/1.4.0/graphics-2d/Canvas",
- "references/1.4.0/graphics-2d/Circle",
- "references/1.4.0/graphics-2d/CircleConfig",
- "references/1.4.0/graphics-2d/Container",
- "references/1.4.0/graphics-2d/ContainerConfig",
- "references/1.4.0/graphics-2d/Context",
- "references/1.4.0/graphics-2d/DD",
- "references/1.4.0/graphics-2d/Easings",
- "references/1.4.0/graphics-2d/Ellipse",
- "references/1.4.0/graphics-2d/EllipseConfig",
- "references/1.4.0/graphics-2d/FastLayer",
- "references/1.4.0/graphics-2d/Filters",
- {
- "group": "Graphics2DLibrary",
- "pages": [
- "references/1.4.0/graphics-2d/Graphics2DLibrary/baseLayer",
- "references/1.4.0/graphics-2d/Graphics2DLibrary/stage"
- ],
- "root": "references/1.4.0/graphics-2d/Graphics2DLibrary"
- },
- "references/1.4.0/graphics-2d/Group",
- "references/1.4.0/graphics-2d/GroupConfig",
- "references/1.4.0/graphics-2d/Image_2",
- "references/1.4.0/graphics-2d/ImageConfig",
- "references/1.4.0/graphics-2d/KonvaEventListener",
- "references/1.4.0/graphics-2d/KonvaEventObject",
- "references/1.4.0/graphics-2d/KonvaPointerEvent",
- "references/1.4.0/graphics-2d/Label",
- "references/1.4.0/graphics-2d/LabelConfig",
- "references/1.4.0/graphics-2d/Layer",
- "references/1.4.0/graphics-2d/LayerConfig",
- "references/1.4.0/graphics-2d/Line",
- "references/1.4.0/graphics-2d/LineConfig",
- "references/1.4.0/graphics-2d/Node_2",
- "references/1.4.0/graphics-2d/NodeConfig",
- "references/1.4.0/graphics-2d/Path",
- "references/1.4.0/graphics-2d/PathConfig",
- "references/1.4.0/graphics-2d/Rect",
- "references/1.4.0/graphics-2d/RectConfig",
- "references/1.4.0/graphics-2d/RegularPolygon",
- "references/1.4.0/graphics-2d/RegularPolygonConfig",
- "references/1.4.0/graphics-2d/Ring",
- "references/1.4.0/graphics-2d/RingConfig",
- "references/1.4.0/graphics-2d/Shape",
- "references/1.4.0/graphics-2d/ShapeConfig",
- "references/1.4.0/graphics-2d/Sprite",
- "references/1.4.0/graphics-2d/SpriteConfig",
- "references/1.4.0/graphics-2d/Stage",
- "references/1.4.0/graphics-2d/StageConfig",
- "references/1.4.0/graphics-2d/Star",
- "references/1.4.0/graphics-2d/StarConfig",
- "references/1.4.0/graphics-2d/Tag",
- "references/1.4.0/graphics-2d/TagConfig",
- "references/1.4.0/graphics-2d/Text_2",
- "references/1.4.0/graphics-2d/TextConfig",
- "references/1.4.0/graphics-2d/TextPath",
- "references/1.4.0/graphics-2d/TextPathConfig",
- "references/1.4.0/graphics-2d/Transform",
- "references/1.4.0/graphics-2d/Transformer_2",
- "references/1.4.0/graphics-2d/TransformerConfig",
- "references/1.4.0/graphics-2d/Tween",
- "references/1.4.0/graphics-2d/TweenConfig",
- "references/1.4.0/graphics-2d/Util",
- "references/1.4.0/graphics-2d/Vector2d",
- "references/1.4.0/graphics-2d/Wedge",
- "references/1.4.0/graphics-2d/WedgeConfig"
- ]
- },
- {
- "dropdown": "Input",
- "pages": [
- "references/1.4.0/input/0-index",
- "references/1.4.0/input/InputEnum",
- {
- "group": "InputLibrary",
- "pages": [
- "references/1.4.0/input/InputLibrary/constructor",
- "references/1.4.0/input/InputLibrary/getDragState",
- "references/1.4.0/input/InputLibrary/getMousePosition",
- "references/1.4.0/input/InputLibrary/getMouseState",
- "references/1.4.0/input/InputLibrary/getPressedKeys",
- "references/1.4.0/input/InputLibrary/getWheelState",
- "references/1.4.0/input/InputLibrary/isDragging",
- "references/1.4.0/input/InputLibrary/isKeyPressed"
- ],
- "root": "references/1.4.0/input/InputLibrary"
- }
- ]
- },
- {
- "dropdown": "Music",
- "pages": [
- "references/1.4.0/music/0-index",
- {
- "group": "MusicLibrary",
- "pages": [
- "references/1.4.0/music/MusicLibrary/load",
- "references/1.4.0/music/MusicLibrary/mute",
- "references/1.4.0/music/MusicLibrary/play"
- ],
- "root": "references/1.4.0/music/MusicLibrary"
- }
- ]
- },
- {
- "dropdown": "Network-Client",
- "pages": [
- "references/1.4.0/network-client/0-index",
- {
- "group": "NetworkClientLibrary",
- "pages": [
- "references/1.4.0/network-client/NetworkClientLibrary/tcp",
- "references/1.4.0/network-client/NetworkClientLibrary/udp"
- ],
- "root": "references/1.4.0/network-client/NetworkClientLibrary"
- },
- {
- "group": "TCPClient",
- "pages": [
- "references/1.4.0/network-client/TCPClient/connect",
- "references/1.4.0/network-client/TCPClient/constructor",
- "references/1.4.0/network-client/TCPClient/getReceivedPackets",
- "references/1.4.0/network-client/TCPClient/isConnected",
- "references/1.4.0/network-client/TCPClient/sendData"
- ],
- "root": "references/1.4.0/network-client/TCPClient"
- },
- {
- "group": "UDPClient",
- "pages": [
- "references/1.4.0/network-client/UDPClient/connect",
- "references/1.4.0/network-client/UDPClient/constructor",
- "references/1.4.0/network-client/UDPClient/getReceivedPackets",
- "references/1.4.0/network-client/UDPClient/isConnected",
- "references/1.4.0/network-client/UDPClient/sendData"
- ],
- "root": "references/1.4.0/network-client/UDPClient"
- }
- ]
- },
- {
- "dropdown": "Network-Server",
- "pages": [
- "references/1.4.0/network-server/0-index",
- {
- "group": "NetworkServerLibrary",
- "pages": [
- "references/1.4.0/network-server/NetworkServerLibrary/tcp",
- "references/1.4.0/network-server/NetworkServerLibrary/udp"
- ],
- "root": "references/1.4.0/network-server/NetworkServerLibrary"
- },
- {
- "group": "TCPServer",
- "pages": [
- "references/1.4.0/network-server/TCPServer/constructor",
- "references/1.4.0/network-server/TCPServer/getConnectedClients",
- "references/1.4.0/network-server/TCPServer/getReceivedPackets",
- "references/1.4.0/network-server/TCPServer/listen",
- "references/1.4.0/network-server/TCPServer/sendToClient",
- "references/1.4.0/network-server/TCPServer/sendToEverybody"
- ],
- "root": "references/1.4.0/network-server/TCPServer"
- },
- {
- "group": "UDPServer",
- "pages": [
- "references/1.4.0/network-server/UDPServer/constructor",
- "references/1.4.0/network-server/UDPServer/getConnectedClients",
- "references/1.4.0/network-server/UDPServer/getReceivedPackets",
- "references/1.4.0/network-server/UDPServer/listen",
- "references/1.4.0/network-server/UDPServer/sendToClient",
- "references/1.4.0/network-server/UDPServer/sendToEverybody"
- ],
- "root": "references/1.4.0/network-server/UDPServer"
- }
- ]
- },
- {
- "dropdown": "Sound",
- "pages": [
- "references/1.4.0/sound/0-index",
- {
- "group": "SoundLibrary",
- "pages": [
- "references/1.4.0/sound/SoundLibrary/load",
- "references/1.4.0/sound/SoundLibrary/mute",
- "references/1.4.0/sound/SoundLibrary/play"
- ],
- "root": "references/1.4.0/sound/SoundLibrary"
- }
- ]
- }
- ]
- },
+ "dropdown": "CLI",
+ "icon": "terminal",
+ "groups": [
{
- "version": "1.4.2",
- "dropdowns": [
- {
- "dropdown": "Asset-Manager",
- "pages": [
- "references/1.4.2/asset-manager/0-index",
- {
- "group": "AssetManagerLibrary",
- "pages": [
- "references/1.4.2/asset-manager/AssetManagerLibrary/getAsset_1",
- "references/1.4.2/asset-manager/AssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.2/asset-manager/AssetManagerLibrary"
- }
- ]
- },
- {
- "dropdown": "Common",
- "pages": [
- "references/1.4.2/common/0-index",
- {
- "group": "ApplicationContext",
- "pages": [
- "references/1.4.2/common/ApplicationContext/delta",
- "references/1.4.2/common/ApplicationContext/isRunning"
- ],
- "root": "references/1.4.2/common/ApplicationContext"
- },
- "references/1.4.2/common/ASSET_MANAGER_LIBRARY",
- {
- "group": "BaseAssetManagerLibrary",
- "pages": [
- "references/1.4.2/common/BaseAssetManagerLibrary/getAsset_1",
- "references/1.4.2/common/BaseAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.2/common/BaseAssetManagerLibrary"
- },
- "references/1.4.2/common/BaseComponentSystemLibrary",
- "references/1.4.2/common/BaseGraphicsLibrary",
- "references/1.4.2/common/BaseInputLibrary",
- {
- "group": "BaseMusicLibrary",
- "pages": [
- "references/1.4.2/common/BaseMusicLibrary/mute",
- "references/1.4.2/common/BaseMusicLibrary/play"
- ],
- "root": "references/1.4.2/common/BaseMusicLibrary"
- },
- "references/1.4.2/common/BaseNetworkLibrary",
- {
- "group": "BaseSoundLibrary",
- "pages": [
- "references/1.4.2/common/BaseSoundLibrary/mute",
- "references/1.4.2/common/BaseSoundLibrary/play"
- ],
- "root": "references/1.4.2/common/BaseSoundLibrary"
- },
- "references/1.4.2/common/ClearContext",
- {
- "group": "ClientLibraryManager",
- "pages": [
- "references/1.4.2/common/ClientLibraryManager/constructor",
- "references/1.4.2/common/ClientLibraryManager/get",
- "references/1.4.2/common/ClientLibraryManager/getAssetManager",
- "references/1.4.2/common/ClientLibraryManager/getComponentSystem",
- "references/1.4.2/common/ClientLibraryManager/getGraphics",
- "references/1.4.2/common/ClientLibraryManager/getInput",
- "references/1.4.2/common/ClientLibraryManager/getMusic",
- "references/1.4.2/common/ClientLibraryManager/getNetwork",
- "references/1.4.2/common/ClientLibraryManager/getSound"
- ],
- "root": "references/1.4.2/common/ClientLibraryManager"
- },
- "references/1.4.2/common/COMPONENT_SYSTEM_LIBRARY",
- {
- "group": "Context",
- "pages": [
- "references/1.4.2/common/Context/app",
- "references/1.4.2/common/Context/constructor",
- "references/1.4.2/common/Context/libs"
- ],
- "root": "references/1.4.2/common/Context"
- },
- "references/1.4.2/common/DefaultLibrariesEnum",
- "references/1.4.2/common/ExecutionContext",
- "references/1.4.2/common/GRAPHICS_LIBRARY",
- {
- "group": "IAssetManagerLibrary",
- "pages": [
- "references/1.4.2/common/IAssetManagerLibrary/getAsset_1",
- "references/1.4.2/common/IAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.2/common/IAssetManagerLibrary"
- },
- "references/1.4.2/common/IComponentSystemLibrary",
- {
- "group": "IConfigRegistry",
- "pages": [
- "references/1.4.2/common/IConfigRegistry/registerConfig"
- ],
- "root": "references/1.4.2/common/IConfigRegistry"
- },
- "references/1.4.2/common/IExposedLibrary",
- "references/1.4.2/common/IGraphicsLibrary",
- "references/1.4.2/common/IInputLibrary",
- "references/1.4.2/common/ILibrary",
- "references/1.4.2/common/IMusicLibrary",
- {
- "group": "IMutableLibrary",
- "pages": [
- "references/1.4.2/common/IMutableLibrary/mute"
- ],
- "root": "references/1.4.2/common/IMutableLibrary"
- },
- "references/1.4.2/common/INetworkLibrary",
- {
- "group": "InitContext",
- "pages": [
- "references/1.4.2/common/InitContext/config",
- "references/1.4.2/common/InitContext/constructor",
- "references/1.4.2/common/InitContext/container",
- "references/1.4.2/common/InitContext/env",
- "references/1.4.2/common/InitContext/files"
- ],
- "root": "references/1.4.2/common/InitContext"
- },
- "references/1.4.2/common/INPUT_LIBRARY",
- {
- "group": "IRunClientOptions",
- "pages": [
- "references/1.4.2/common/IRunClientOptions/container",
- "references/1.4.2/common/IRunClientOptions/env",
- "references/1.4.2/common/IRunClientOptions/files"
- ],
- "root": "references/1.4.2/common/IRunClientOptions"
- },
- "references/1.4.2/common/IRunnerLibrary",
- "references/1.4.2/common/IRunOptions",
- {
- "group": "IRunServerOptions",
- "pages": [
- "references/1.4.2/common/IRunServerOptions/env",
- "references/1.4.2/common/IRunServerOptions/files"
- ],
- "root": "references/1.4.2/common/IRunServerOptions"
- },
- "references/1.4.2/common/ISoundLibrary",
- {
- "group": "Library",
- "pages": [
- "references/1.4.2/common/Library/_relationship",
- "references/1.4.2/common/Library/constructor"
- ],
- "root": "references/1.4.2/common/Library"
- },
- {
- "group": "LibraryContext",
- "pages": [
- "references/1.4.2/common/LibraryContext/status"
- ],
- "root": "references/1.4.2/common/LibraryContext"
- },
- {
- "group": "LibraryHandle",
- "pages": [
- "references/1.4.2/common/LibraryHandle/constructor",
- "references/1.4.2/common/LibraryHandle/context",
- "references/1.4.2/common/LibraryHandle/library",
- "references/1.4.2/common/LibraryHandle/symbol"
- ],
- "root": "references/1.4.2/common/LibraryHandle"
- },
- {
- "group": "LibraryManager",
- "pages": [
- "references/1.4.2/common/LibraryManager/constructor",
- "references/1.4.2/common/LibraryManager/getAssetManager",
- "references/1.4.2/common/LibraryManager/getComponentSystem",
- "references/1.4.2/common/LibraryManager/getGraphics",
- "references/1.4.2/common/LibraryManager/getInput",
- "references/1.4.2/common/LibraryManager/getMusic",
- "references/1.4.2/common/LibraryManager/getNetwork",
- "references/1.4.2/common/LibraryManager/getSound"
- ],
- "root": "references/1.4.2/common/LibraryManager"
- },
- "references/1.4.2/common/LibraryStatusEnum",
- "references/1.4.2/common/MUSIC_LIBRARY",
- "references/1.4.2/common/NETWORK_LIBRARY",
- {
- "group": "NfConfigException",
- "pages": [
- "references/1.4.2/common/NfConfigException/code",
- "references/1.4.2/common/NfConfigException/constructor"
- ],
- "root": "references/1.4.2/common/NfConfigException"
- },
- {
- "group": "NfFetchException",
- "pages": [
- "references/1.4.2/common/NfFetchException/code",
- "references/1.4.2/common/NfFetchException/constructor"
- ],
- "root": "references/1.4.2/common/NfFetchException"
- },
- {
- "group": "NfFile",
- "pages": [
- "references/1.4.2/common/NfFile/arrayBuffer",
- "references/1.4.2/common/NfFile/blob",
- "references/1.4.2/common/NfFile/bytes",
- "references/1.4.2/common/NfFile/constructor",
- "references/1.4.2/common/NfFile/formData",
- "references/1.4.2/common/NfFile/json",
- "references/1.4.2/common/NfFile/path",
- "references/1.4.2/common/NfFile/text"
- ],
- "root": "references/1.4.2/common/NfFile"
- },
- {
- "group": "NfNotFound",
- "pages": [
- "references/1.4.2/common/NfNotFound/code",
- "references/1.4.2/common/NfNotFound/constructor"
- ],
- "root": "references/1.4.2/common/NfNotFound"
- },
- {
- "group": "NfNotInitializedException",
- "pages": [
- "references/1.4.2/common/NfNotInitializedException/code",
- "references/1.4.2/common/NfNotInitializedException/constructor"
- ],
- "root": "references/1.4.2/common/NfNotInitializedException"
- },
- "references/1.4.2/common/SOUND_LIBRARY"
- ]
- },
- {
- "dropdown": "Config",
- "pages": [
- "references/1.4.2/config/0-index",
- "references/1.4.2/config/Default",
- "references/1.4.2/config/IsIpOrURL",
- "references/1.4.2/config/TransformToBoolean"
- ]
- },
- {
- "dropdown": "Core",
- "pages": [
- "references/1.4.2/core/0-index",
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.4.2/core/NanoforgeClient/useGraphics",
- "references/1.4.2/core/NanoforgeClient/useInput",
- "references/1.4.2/core/NanoforgeClient/useSound"
- ],
- "root": "references/1.4.2/core/NanoforgeClient"
- },
- "references/1.4.2/core/NanoforgeFactory",
- "references/1.4.2/core/NanoforgeServer"
- ]
- },
- {
- "dropdown": "Core-Editor",
- "pages": [
- "references/1.4.2/core-editor/0-index",
- "references/1.4.2/core-editor/CoreEvents",
- "references/1.4.2/core-editor/EditorEvents",
- {
- "group": "EventEmitter",
- "pages": [
- "references/1.4.2/core-editor/EventEmitter/constructor",
- "references/1.4.2/core-editor/EventEmitter/emit",
- "references/1.4.2/core-editor/EventEmitter/on",
- "references/1.4.2/core-editor/EventEmitter/runEvents"
- ],
- "root": "references/1.4.2/core-editor/EventEmitter"
- },
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.4.2/core-editor/NanoforgeClient/useGraphics",
- "references/1.4.2/core-editor/NanoforgeClient/useInput",
- "references/1.4.2/core-editor/NanoforgeClient/useSound"
- ],
- "root": "references/1.4.2/core-editor/NanoforgeClient"
- },
- "references/1.4.2/core-editor/NanoforgeFactory",
- "references/1.4.2/core-editor/NanoforgeServer"
- ]
- },
- {
- "dropdown": "ECS-Client",
- "pages": [
- "references/1.4.2/ecs-client/0-index",
- {
- "group": "ECSClientLibrary",
- "pages": [
- "references/1.4.2/ecs-client/ECSClientLibrary/constructor"
- ],
- "root": "references/1.4.2/ecs-client/ECSClientLibrary"
- }
- ]
- },
- {
- "dropdown": "ECS-Lib",
- "pages": [
- "references/1.4.2/ecs-lib/0-index",
- {
- "group": "AbstractECSLibrary",
- "pages": [
- "references/1.4.2/ecs-lib/AbstractECSLibrary/_registry",
- "references/1.4.2/ecs-lib/AbstractECSLibrary/constructor",
- "references/1.4.2/ecs-lib/AbstractECSLibrary/module",
- "references/1.4.2/ecs-lib/AbstractECSLibrary/path",
- "references/1.4.2/ecs-lib/AbstractECSLibrary/registry"
- ],
- "root": "references/1.4.2/ecs-lib/AbstractECSLibrary"
- },
- "references/1.4.2/ecs-lib/Component",
- "references/1.4.2/ecs-lib/EditorComponentManifest",
- "references/1.4.2/ecs-lib/EditorSystemManifest",
- {
- "group": "Entity",
- "pages": [
- "references/1.4.2/ecs-lib/Entity/getId"
- ],
- "root": "references/1.4.2/ecs-lib/Entity"
- },
- {
- "group": "Registry",
- "pages": [
- "references/1.4.2/ecs-lib/Registry/addComponent",
- "references/1.4.2/ecs-lib/Registry/addSystem",
- "references/1.4.2/ecs-lib/Registry/clearEntities",
- "references/1.4.2/ecs-lib/Registry/clearSystems",
- "references/1.4.2/ecs-lib/Registry/entityFromIndex",
- "references/1.4.2/ecs-lib/Registry/getComponents",
- "references/1.4.2/ecs-lib/Registry/getComponentsConst",
- "references/1.4.2/ecs-lib/Registry/getEntityComponent",
- "references/1.4.2/ecs-lib/Registry/getEntityComponentConst",
- "references/1.4.2/ecs-lib/Registry/getIndexedZipper",
- "references/1.4.2/ecs-lib/Registry/getZipper",
- "references/1.4.2/ecs-lib/Registry/killEntity",
- "references/1.4.2/ecs-lib/Registry/maxEntities",
- "references/1.4.2/ecs-lib/Registry/registerComponent",
- "references/1.4.2/ecs-lib/Registry/removeComponent",
- "references/1.4.2/ecs-lib/Registry/removeSystem",
- "references/1.4.2/ecs-lib/Registry/runSystems",
- "references/1.4.2/ecs-lib/Registry/spawnEntity"
- ],
- "root": "references/1.4.2/ecs-lib/Registry"
- },
- {
- "group": "SparseArray",
- "pages": [
- "references/1.4.2/ecs-lib/SparseArray/clear",
- "references/1.4.2/ecs-lib/SparseArray/empty",
- "references/1.4.2/ecs-lib/SparseArray/erase",
- "references/1.4.2/ecs-lib/SparseArray/get",
- "references/1.4.2/ecs-lib/SparseArray/getConst",
- "references/1.4.2/ecs-lib/SparseArray/getIndex",
- "references/1.4.2/ecs-lib/SparseArray/insertAt_1",
- "references/1.4.2/ecs-lib/SparseArray/insertAt",
- "references/1.4.2/ecs-lib/SparseArray/resize",
- "references/1.4.2/ecs-lib/SparseArray/set",
- "references/1.4.2/ecs-lib/SparseArray/setByCopy",
- "references/1.4.2/ecs-lib/SparseArray/setByMove",
- "references/1.4.2/ecs-lib/SparseArray/size"
- ],
- "root": "references/1.4.2/ecs-lib/SparseArray"
- },
- "references/1.4.2/ecs-lib/System"
- ]
- },
- {
- "dropdown": "ECS-Server",
- "pages": [
- "references/1.4.2/ecs-server/0-index",
- {
- "group": "ECSServerLibrary",
- "pages": [
- "references/1.4.2/ecs-server/ECSServerLibrary/constructor"
- ],
- "root": "references/1.4.2/ecs-server/ECSServerLibrary"
- },
- "references/1.4.2/ecs-server/Module"
- ]
- },
- {
- "dropdown": "Graphics-2d",
- "pages": [
- "references/1.4.2/graphics-2d/0-index",
- "references/1.4.2/graphics-2d/Animation_2",
- "references/1.4.2/graphics-2d/Arc",
- "references/1.4.2/graphics-2d/ArcConfig",
- "references/1.4.2/graphics-2d/Arrow",
- "references/1.4.2/graphics-2d/ArrowConfig",
- "references/1.4.2/graphics-2d/Canvas",
- "references/1.4.2/graphics-2d/Circle",
- "references/1.4.2/graphics-2d/CircleConfig",
- "references/1.4.2/graphics-2d/Container",
- "references/1.4.2/graphics-2d/ContainerConfig",
- "references/1.4.2/graphics-2d/Context",
- "references/1.4.2/graphics-2d/DD",
- "references/1.4.2/graphics-2d/Easings",
- "references/1.4.2/graphics-2d/Ellipse",
- "references/1.4.2/graphics-2d/EllipseConfig",
- "references/1.4.2/graphics-2d/FastLayer",
- "references/1.4.2/graphics-2d/Filters",
- {
- "group": "Graphics2DLibrary",
- "pages": [
- "references/1.4.2/graphics-2d/Graphics2DLibrary/baseLayer",
- "references/1.4.2/graphics-2d/Graphics2DLibrary/stage"
- ],
- "root": "references/1.4.2/graphics-2d/Graphics2DLibrary"
- },
- "references/1.4.2/graphics-2d/Group",
- "references/1.4.2/graphics-2d/GroupConfig",
- "references/1.4.2/graphics-2d/Image_2",
- "references/1.4.2/graphics-2d/ImageConfig",
- "references/1.4.2/graphics-2d/KonvaEventListener",
- "references/1.4.2/graphics-2d/KonvaEventObject",
- "references/1.4.2/graphics-2d/KonvaPointerEvent",
- "references/1.4.2/graphics-2d/Label",
- "references/1.4.2/graphics-2d/LabelConfig",
- "references/1.4.2/graphics-2d/Layer",
- "references/1.4.2/graphics-2d/LayerConfig",
- "references/1.4.2/graphics-2d/Line",
- "references/1.4.2/graphics-2d/LineConfig",
- "references/1.4.2/graphics-2d/Node_2",
- "references/1.4.2/graphics-2d/NodeConfig",
- "references/1.4.2/graphics-2d/Path",
- "references/1.4.2/graphics-2d/PathConfig",
- "references/1.4.2/graphics-2d/Rect",
- "references/1.4.2/graphics-2d/RectConfig",
- "references/1.4.2/graphics-2d/RegularPolygon",
- "references/1.4.2/graphics-2d/RegularPolygonConfig",
- "references/1.4.2/graphics-2d/Ring",
- "references/1.4.2/graphics-2d/RingConfig",
- "references/1.4.2/graphics-2d/Shape",
- "references/1.4.2/graphics-2d/ShapeConfig",
- "references/1.4.2/graphics-2d/Sprite",
- "references/1.4.2/graphics-2d/SpriteConfig",
- "references/1.4.2/graphics-2d/Stage",
- "references/1.4.2/graphics-2d/StageConfig",
- "references/1.4.2/graphics-2d/Star",
- "references/1.4.2/graphics-2d/StarConfig",
- "references/1.4.2/graphics-2d/Tag",
- "references/1.4.2/graphics-2d/TagConfig",
- "references/1.4.2/graphics-2d/Text_2",
- "references/1.4.2/graphics-2d/TextConfig",
- "references/1.4.2/graphics-2d/TextPath",
- "references/1.4.2/graphics-2d/TextPathConfig",
- "references/1.4.2/graphics-2d/Transform",
- "references/1.4.2/graphics-2d/Transformer_2",
- "references/1.4.2/graphics-2d/TransformerConfig",
- "references/1.4.2/graphics-2d/Tween",
- "references/1.4.2/graphics-2d/TweenConfig",
- "references/1.4.2/graphics-2d/Util",
- "references/1.4.2/graphics-2d/Vector2d",
- "references/1.4.2/graphics-2d/Wedge",
- "references/1.4.2/graphics-2d/WedgeConfig"
- ]
- },
- {
- "dropdown": "Input",
- "pages": [
- "references/1.4.2/input/0-index",
- "references/1.4.2/input/InputEnum",
- {
- "group": "InputLibrary",
- "pages": [
- "references/1.4.2/input/InputLibrary/constructor",
- "references/1.4.2/input/InputLibrary/getDragState",
- "references/1.4.2/input/InputLibrary/getMousePosition",
- "references/1.4.2/input/InputLibrary/getMouseState",
- "references/1.4.2/input/InputLibrary/getPressedKeys",
- "references/1.4.2/input/InputLibrary/getWheelState",
- "references/1.4.2/input/InputLibrary/isDragging",
- "references/1.4.2/input/InputLibrary/isKeyPressed"
- ],
- "root": "references/1.4.2/input/InputLibrary"
- }
- ]
- },
- {
- "dropdown": "Music",
- "pages": [
- "references/1.4.2/music/0-index",
- {
- "group": "MusicLibrary",
- "pages": [
- "references/1.4.2/music/MusicLibrary/load",
- "references/1.4.2/music/MusicLibrary/mute",
- "references/1.4.2/music/MusicLibrary/play"
- ],
- "root": "references/1.4.2/music/MusicLibrary"
- }
- ]
- },
- {
- "dropdown": "Network-Client",
- "pages": [
- "references/1.4.2/network-client/0-index",
- {
- "group": "NetworkClientLibrary",
- "pages": [
- "references/1.4.2/network-client/NetworkClientLibrary/tcp",
- "references/1.4.2/network-client/NetworkClientLibrary/udp"
- ],
- "root": "references/1.4.2/network-client/NetworkClientLibrary"
- },
- {
- "group": "TCPClient",
- "pages": [
- "references/1.4.2/network-client/TCPClient/connect",
- "references/1.4.2/network-client/TCPClient/constructor",
- "references/1.4.2/network-client/TCPClient/getReceivedPackets",
- "references/1.4.2/network-client/TCPClient/isConnected",
- "references/1.4.2/network-client/TCPClient/sendData"
- ],
- "root": "references/1.4.2/network-client/TCPClient"
- },
- {
- "group": "UDPClient",
- "pages": [
- "references/1.4.2/network-client/UDPClient/connect",
- "references/1.4.2/network-client/UDPClient/constructor",
- "references/1.4.2/network-client/UDPClient/getReceivedPackets",
- "references/1.4.2/network-client/UDPClient/isConnected",
- "references/1.4.2/network-client/UDPClient/sendData"
- ],
- "root": "references/1.4.2/network-client/UDPClient"
- }
- ]
- },
- {
- "dropdown": "Network-Server",
- "pages": [
- "references/1.4.2/network-server/0-index",
- {
- "group": "NetworkServerLibrary",
- "pages": [
- "references/1.4.2/network-server/NetworkServerLibrary/tcp",
- "references/1.4.2/network-server/NetworkServerLibrary/udp"
- ],
- "root": "references/1.4.2/network-server/NetworkServerLibrary"
- },
- {
- "group": "TCPServer",
- "pages": [
- "references/1.4.2/network-server/TCPServer/constructor",
- "references/1.4.2/network-server/TCPServer/getConnectedClients",
- "references/1.4.2/network-server/TCPServer/getReceivedPackets",
- "references/1.4.2/network-server/TCPServer/listen",
- "references/1.4.2/network-server/TCPServer/sendToClient",
- "references/1.4.2/network-server/TCPServer/sendToEverybody"
- ],
- "root": "references/1.4.2/network-server/TCPServer"
- },
- {
- "group": "UDPServer",
- "pages": [
- "references/1.4.2/network-server/UDPServer/constructor",
- "references/1.4.2/network-server/UDPServer/getConnectedClients",
- "references/1.4.2/network-server/UDPServer/getReceivedPackets",
- "references/1.4.2/network-server/UDPServer/listen",
- "references/1.4.2/network-server/UDPServer/sendToClient",
- "references/1.4.2/network-server/UDPServer/sendToEverybody"
- ],
- "root": "references/1.4.2/network-server/UDPServer"
- }
- ]
- },
- {
- "dropdown": "Sound",
- "pages": [
- "references/1.4.2/sound/0-index",
- {
- "group": "SoundLibrary",
- "pages": [
- "references/1.4.2/sound/SoundLibrary/load",
- "references/1.4.2/sound/SoundLibrary/mute",
- "references/1.4.2/sound/SoundLibrary/play"
- ],
- "root": "references/1.4.2/sound/SoundLibrary"
- }
- ]
- }
- ]
+ "group": "CLI",
+ "pages": {
+ "$ref": "./docs/cli/navigation.json"
+ }
},
{
- "version": "1.4.1",
- "dropdowns": [
- {
- "dropdown": "Asset-Manager",
- "pages": [
- "references/1.4.1/asset-manager/0-index",
- {
- "group": "AssetManagerLibrary",
- "pages": [
- "references/1.4.1/asset-manager/AssetManagerLibrary/getAsset_1",
- "references/1.4.1/asset-manager/AssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.1/asset-manager/AssetManagerLibrary"
- }
- ]
- },
- {
- "dropdown": "Common",
- "pages": [
- "references/1.4.1/common/0-index",
- {
- "group": "ApplicationContext",
- "pages": [
- "references/1.4.1/common/ApplicationContext/delta",
- "references/1.4.1/common/ApplicationContext/isRunning"
- ],
- "root": "references/1.4.1/common/ApplicationContext"
- },
- "references/1.4.1/common/ASSET_MANAGER_LIBRARY",
- {
- "group": "BaseAssetManagerLibrary",
- "pages": [
- "references/1.4.1/common/BaseAssetManagerLibrary/getAsset_1",
- "references/1.4.1/common/BaseAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.1/common/BaseAssetManagerLibrary"
- },
- "references/1.4.1/common/BaseComponentSystemLibrary",
- "references/1.4.1/common/BaseGraphicsLibrary",
- "references/1.4.1/common/BaseInputLibrary",
- {
- "group": "BaseMusicLibrary",
- "pages": [
- "references/1.4.1/common/BaseMusicLibrary/mute",
- "references/1.4.1/common/BaseMusicLibrary/play"
- ],
- "root": "references/1.4.1/common/BaseMusicLibrary"
- },
- "references/1.4.1/common/BaseNetworkLibrary",
- {
- "group": "BaseSoundLibrary",
- "pages": [
- "references/1.4.1/common/BaseSoundLibrary/mute",
- "references/1.4.1/common/BaseSoundLibrary/play"
- ],
- "root": "references/1.4.1/common/BaseSoundLibrary"
- },
- "references/1.4.1/common/ClearContext",
- {
- "group": "ClientLibraryManager",
- "pages": [
- "references/1.4.1/common/ClientLibraryManager/constructor",
- "references/1.4.1/common/ClientLibraryManager/get",
- "references/1.4.1/common/ClientLibraryManager/getAssetManager",
- "references/1.4.1/common/ClientLibraryManager/getComponentSystem",
- "references/1.4.1/common/ClientLibraryManager/getGraphics",
- "references/1.4.1/common/ClientLibraryManager/getInput",
- "references/1.4.1/common/ClientLibraryManager/getMusic",
- "references/1.4.1/common/ClientLibraryManager/getNetwork",
- "references/1.4.1/common/ClientLibraryManager/getSound"
- ],
- "root": "references/1.4.1/common/ClientLibraryManager"
- },
- "references/1.4.1/common/COMPONENT_SYSTEM_LIBRARY",
- {
- "group": "Context",
- "pages": [
- "references/1.4.1/common/Context/app",
- "references/1.4.1/common/Context/constructor",
- "references/1.4.1/common/Context/libs"
- ],
- "root": "references/1.4.1/common/Context"
- },
- "references/1.4.1/common/DefaultLibrariesEnum",
- "references/1.4.1/common/ExecutionContext",
- "references/1.4.1/common/GRAPHICS_LIBRARY",
- {
- "group": "IAssetManagerLibrary",
- "pages": [
- "references/1.4.1/common/IAssetManagerLibrary/getAsset_1",
- "references/1.4.1/common/IAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.4.1/common/IAssetManagerLibrary"
- },
- "references/1.4.1/common/IComponentSystemLibrary",
- {
- "group": "IConfigRegistry",
- "pages": [
- "references/1.4.1/common/IConfigRegistry/registerConfig"
- ],
- "root": "references/1.4.1/common/IConfigRegistry"
- },
- "references/1.4.1/common/IExposedLibrary",
- "references/1.4.1/common/IGraphicsLibrary",
- "references/1.4.1/common/IInputLibrary",
- "references/1.4.1/common/ILibrary",
- "references/1.4.1/common/IMusicLibrary",
- {
- "group": "IMutableLibrary",
- "pages": [
- "references/1.4.1/common/IMutableLibrary/mute"
- ],
- "root": "references/1.4.1/common/IMutableLibrary"
- },
- "references/1.4.1/common/INetworkLibrary",
- {
- "group": "InitContext",
- "pages": [
- "references/1.4.1/common/InitContext/config",
- "references/1.4.1/common/InitContext/constructor",
- "references/1.4.1/common/InitContext/container",
- "references/1.4.1/common/InitContext/env",
- "references/1.4.1/common/InitContext/files"
- ],
- "root": "references/1.4.1/common/InitContext"
- },
- "references/1.4.1/common/INPUT_LIBRARY",
- {
- "group": "IRunClientOptions",
- "pages": [
- "references/1.4.1/common/IRunClientOptions/container",
- "references/1.4.1/common/IRunClientOptions/env",
- "references/1.4.1/common/IRunClientOptions/files"
- ],
- "root": "references/1.4.1/common/IRunClientOptions"
- },
- "references/1.4.1/common/IRunnerLibrary",
- "references/1.4.1/common/IRunOptions",
- {
- "group": "IRunServerOptions",
- "pages": [
- "references/1.4.1/common/IRunServerOptions/env",
- "references/1.4.1/common/IRunServerOptions/files"
- ],
- "root": "references/1.4.1/common/IRunServerOptions"
- },
- "references/1.4.1/common/ISoundLibrary",
- {
- "group": "Library",
- "pages": [
- "references/1.4.1/common/Library/_relationship",
- "references/1.4.1/common/Library/constructor"
- ],
- "root": "references/1.4.1/common/Library"
- },
- {
- "group": "LibraryContext",
- "pages": [
- "references/1.4.1/common/LibraryContext/status"
- ],
- "root": "references/1.4.1/common/LibraryContext"
- },
- {
- "group": "LibraryHandle",
- "pages": [
- "references/1.4.1/common/LibraryHandle/constructor",
- "references/1.4.1/common/LibraryHandle/context",
- "references/1.4.1/common/LibraryHandle/library",
- "references/1.4.1/common/LibraryHandle/symbol"
- ],
- "root": "references/1.4.1/common/LibraryHandle"
- },
- {
- "group": "LibraryManager",
- "pages": [
- "references/1.4.1/common/LibraryManager/constructor",
- "references/1.4.1/common/LibraryManager/getAssetManager",
- "references/1.4.1/common/LibraryManager/getComponentSystem",
- "references/1.4.1/common/LibraryManager/getGraphics",
- "references/1.4.1/common/LibraryManager/getInput",
- "references/1.4.1/common/LibraryManager/getMusic",
- "references/1.4.1/common/LibraryManager/getNetwork",
- "references/1.4.1/common/LibraryManager/getSound"
- ],
- "root": "references/1.4.1/common/LibraryManager"
- },
- "references/1.4.1/common/LibraryStatusEnum",
- "references/1.4.1/common/MUSIC_LIBRARY",
- "references/1.4.1/common/NETWORK_LIBRARY",
- {
- "group": "NfConfigException",
- "pages": [
- "references/1.4.1/common/NfConfigException/code",
- "references/1.4.1/common/NfConfigException/constructor"
- ],
- "root": "references/1.4.1/common/NfConfigException"
- },
- {
- "group": "NfFetchException",
- "pages": [
- "references/1.4.1/common/NfFetchException/code",
- "references/1.4.1/common/NfFetchException/constructor"
- ],
- "root": "references/1.4.1/common/NfFetchException"
- },
- {
- "group": "NfFile",
- "pages": [
- "references/1.4.1/common/NfFile/arrayBuffer",
- "references/1.4.1/common/NfFile/blob",
- "references/1.4.1/common/NfFile/bytes",
- "references/1.4.1/common/NfFile/constructor",
- "references/1.4.1/common/NfFile/formData",
- "references/1.4.1/common/NfFile/json",
- "references/1.4.1/common/NfFile/path",
- "references/1.4.1/common/NfFile/text"
- ],
- "root": "references/1.4.1/common/NfFile"
- },
- {
- "group": "NfNotFound",
- "pages": [
- "references/1.4.1/common/NfNotFound/code",
- "references/1.4.1/common/NfNotFound/constructor"
- ],
- "root": "references/1.4.1/common/NfNotFound"
- },
- {
- "group": "NfNotInitializedException",
- "pages": [
- "references/1.4.1/common/NfNotInitializedException/code",
- "references/1.4.1/common/NfNotInitializedException/constructor"
- ],
- "root": "references/1.4.1/common/NfNotInitializedException"
- },
- "references/1.4.1/common/SOUND_LIBRARY"
- ]
- },
- {
- "dropdown": "Config",
- "pages": [
- "references/1.4.1/config/0-index",
- "references/1.4.1/config/Default",
- "references/1.4.1/config/IsIpOrURL",
- "references/1.4.1/config/TransformToBoolean"
- ]
- },
- {
- "dropdown": "Core",
- "pages": [
- "references/1.4.1/core/0-index",
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.4.1/core/NanoforgeClient/useGraphics",
- "references/1.4.1/core/NanoforgeClient/useInput",
- "references/1.4.1/core/NanoforgeClient/useSound"
- ],
- "root": "references/1.4.1/core/NanoforgeClient"
- },
- "references/1.4.1/core/NanoforgeFactory",
- "references/1.4.1/core/NanoforgeServer"
- ]
- },
- {
- "dropdown": "Core-Editor",
- "pages": [
- "references/1.4.1/core-editor/0-index",
- "references/1.4.1/core-editor/CoreEvents",
- "references/1.4.1/core-editor/EditorEvents",
- {
- "group": "EventEmitter",
- "pages": [
- "references/1.4.1/core-editor/EventEmitter/constructor",
- "references/1.4.1/core-editor/EventEmitter/emit",
- "references/1.4.1/core-editor/EventEmitter/on",
- "references/1.4.1/core-editor/EventEmitter/runEvents"
- ],
- "root": "references/1.4.1/core-editor/EventEmitter"
- },
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.4.1/core-editor/NanoforgeClient/useGraphics",
- "references/1.4.1/core-editor/NanoforgeClient/useInput",
- "references/1.4.1/core-editor/NanoforgeClient/useSound"
- ],
- "root": "references/1.4.1/core-editor/NanoforgeClient"
- },
- "references/1.4.1/core-editor/NanoforgeFactory",
- "references/1.4.1/core-editor/NanoforgeServer"
- ]
- },
- {
- "dropdown": "ECS-Client",
- "pages": [
- "references/1.4.1/ecs-client/0-index",
- {
- "group": "ECSClientLibrary",
- "pages": [
- "references/1.4.1/ecs-client/ECSClientLibrary/constructor"
- ],
- "root": "references/1.4.1/ecs-client/ECSClientLibrary"
- }
- ]
- },
- {
- "dropdown": "ECS-Lib",
- "pages": [
- "references/1.4.1/ecs-lib/0-index",
- {
- "group": "AbstractECSLibrary",
- "pages": [
- "references/1.4.1/ecs-lib/AbstractECSLibrary/_registry",
- "references/1.4.1/ecs-lib/AbstractECSLibrary/constructor",
- "references/1.4.1/ecs-lib/AbstractECSLibrary/module",
- "references/1.4.1/ecs-lib/AbstractECSLibrary/path",
- "references/1.4.1/ecs-lib/AbstractECSLibrary/registry"
- ],
- "root": "references/1.4.1/ecs-lib/AbstractECSLibrary"
- },
- "references/1.4.1/ecs-lib/Component",
- "references/1.4.1/ecs-lib/EditorComponentManifest",
- "references/1.4.1/ecs-lib/EditorSystemManifest",
- {
- "group": "Entity",
- "pages": [
- "references/1.4.1/ecs-lib/Entity/getId"
- ],
- "root": "references/1.4.1/ecs-lib/Entity"
- },
- {
- "group": "Registry",
- "pages": [
- "references/1.4.1/ecs-lib/Registry/addComponent",
- "references/1.4.1/ecs-lib/Registry/addSystem",
- "references/1.4.1/ecs-lib/Registry/clearEntities",
- "references/1.4.1/ecs-lib/Registry/clearSystems",
- "references/1.4.1/ecs-lib/Registry/entityFromIndex",
- "references/1.4.1/ecs-lib/Registry/getComponents",
- "references/1.4.1/ecs-lib/Registry/getComponentsConst",
- "references/1.4.1/ecs-lib/Registry/getEntityComponent",
- "references/1.4.1/ecs-lib/Registry/getEntityComponentConst",
- "references/1.4.1/ecs-lib/Registry/getIndexedZipper",
- "references/1.4.1/ecs-lib/Registry/getZipper",
- "references/1.4.1/ecs-lib/Registry/killEntity",
- "references/1.4.1/ecs-lib/Registry/maxEntities",
- "references/1.4.1/ecs-lib/Registry/registerComponent",
- "references/1.4.1/ecs-lib/Registry/removeComponent",
- "references/1.4.1/ecs-lib/Registry/removeSystem",
- "references/1.4.1/ecs-lib/Registry/runSystems",
- "references/1.4.1/ecs-lib/Registry/spawnEntity"
- ],
- "root": "references/1.4.1/ecs-lib/Registry"
- },
- {
- "group": "SparseArray",
- "pages": [
- "references/1.4.1/ecs-lib/SparseArray/clear",
- "references/1.4.1/ecs-lib/SparseArray/empty",
- "references/1.4.1/ecs-lib/SparseArray/erase",
- "references/1.4.1/ecs-lib/SparseArray/get",
- "references/1.4.1/ecs-lib/SparseArray/getConst",
- "references/1.4.1/ecs-lib/SparseArray/getIndex",
- "references/1.4.1/ecs-lib/SparseArray/insertAt_1",
- "references/1.4.1/ecs-lib/SparseArray/insertAt",
- "references/1.4.1/ecs-lib/SparseArray/resize",
- "references/1.4.1/ecs-lib/SparseArray/set",
- "references/1.4.1/ecs-lib/SparseArray/setByCopy",
- "references/1.4.1/ecs-lib/SparseArray/setByMove",
- "references/1.4.1/ecs-lib/SparseArray/size"
- ],
- "root": "references/1.4.1/ecs-lib/SparseArray"
- },
- "references/1.4.1/ecs-lib/System"
- ]
- },
- {
- "dropdown": "ECS-Server",
- "pages": [
- "references/1.4.1/ecs-server/0-index",
- {
- "group": "ECSServerLibrary",
- "pages": [
- "references/1.4.1/ecs-server/ECSServerLibrary/constructor"
- ],
- "root": "references/1.4.1/ecs-server/ECSServerLibrary"
- },
- "references/1.4.1/ecs-server/Module"
- ]
- },
- {
- "dropdown": "Graphics-2d",
- "pages": [
- "references/1.4.1/graphics-2d/0-index",
- "references/1.4.1/graphics-2d/Animation_2",
- "references/1.4.1/graphics-2d/Arc",
- "references/1.4.1/graphics-2d/ArcConfig",
- "references/1.4.1/graphics-2d/Arrow",
- "references/1.4.1/graphics-2d/ArrowConfig",
- "references/1.4.1/graphics-2d/Canvas",
- "references/1.4.1/graphics-2d/Circle",
- "references/1.4.1/graphics-2d/CircleConfig",
- "references/1.4.1/graphics-2d/Container",
- "references/1.4.1/graphics-2d/ContainerConfig",
- "references/1.4.1/graphics-2d/Context",
- "references/1.4.1/graphics-2d/DD",
- "references/1.4.1/graphics-2d/Easings",
- "references/1.4.1/graphics-2d/Ellipse",
- "references/1.4.1/graphics-2d/EllipseConfig",
- "references/1.4.1/graphics-2d/FastLayer",
- "references/1.4.1/graphics-2d/Filters",
- {
- "group": "Graphics2DLibrary",
- "pages": [
- "references/1.4.1/graphics-2d/Graphics2DLibrary/baseLayer",
- "references/1.4.1/graphics-2d/Graphics2DLibrary/stage"
- ],
- "root": "references/1.4.1/graphics-2d/Graphics2DLibrary"
- },
- "references/1.4.1/graphics-2d/Group",
- "references/1.4.1/graphics-2d/GroupConfig",
- "references/1.4.1/graphics-2d/Image_2",
- "references/1.4.1/graphics-2d/ImageConfig",
- "references/1.4.1/graphics-2d/KonvaEventListener",
- "references/1.4.1/graphics-2d/KonvaEventObject",
- "references/1.4.1/graphics-2d/KonvaPointerEvent",
- "references/1.4.1/graphics-2d/Label",
- "references/1.4.1/graphics-2d/LabelConfig",
- "references/1.4.1/graphics-2d/Layer",
- "references/1.4.1/graphics-2d/LayerConfig",
- "references/1.4.1/graphics-2d/Line",
- "references/1.4.1/graphics-2d/LineConfig",
- "references/1.4.1/graphics-2d/Node_2",
- "references/1.4.1/graphics-2d/NodeConfig",
- "references/1.4.1/graphics-2d/Path",
- "references/1.4.1/graphics-2d/PathConfig",
- "references/1.4.1/graphics-2d/Rect",
- "references/1.4.1/graphics-2d/RectConfig",
- "references/1.4.1/graphics-2d/RegularPolygon",
- "references/1.4.1/graphics-2d/RegularPolygonConfig",
- "references/1.4.1/graphics-2d/Ring",
- "references/1.4.1/graphics-2d/RingConfig",
- "references/1.4.1/graphics-2d/Shape",
- "references/1.4.1/graphics-2d/ShapeConfig",
- "references/1.4.1/graphics-2d/Sprite",
- "references/1.4.1/graphics-2d/SpriteConfig",
- "references/1.4.1/graphics-2d/Stage",
- "references/1.4.1/graphics-2d/StageConfig",
- "references/1.4.1/graphics-2d/Star",
- "references/1.4.1/graphics-2d/StarConfig",
- "references/1.4.1/graphics-2d/Tag",
- "references/1.4.1/graphics-2d/TagConfig",
- "references/1.4.1/graphics-2d/Text_2",
- "references/1.4.1/graphics-2d/TextConfig",
- "references/1.4.1/graphics-2d/TextPath",
- "references/1.4.1/graphics-2d/TextPathConfig",
- "references/1.4.1/graphics-2d/Transform",
- "references/1.4.1/graphics-2d/Transformer_2",
- "references/1.4.1/graphics-2d/TransformerConfig",
- "references/1.4.1/graphics-2d/Tween",
- "references/1.4.1/graphics-2d/TweenConfig",
- "references/1.4.1/graphics-2d/Util",
- "references/1.4.1/graphics-2d/Vector2d",
- "references/1.4.1/graphics-2d/Wedge",
- "references/1.4.1/graphics-2d/WedgeConfig"
- ]
- },
- {
- "dropdown": "Input",
- "pages": [
- "references/1.4.1/input/0-index",
- "references/1.4.1/input/InputEnum",
- {
- "group": "InputLibrary",
- "pages": [
- "references/1.4.1/input/InputLibrary/constructor",
- "references/1.4.1/input/InputLibrary/getDragState",
- "references/1.4.1/input/InputLibrary/getMousePosition",
- "references/1.4.1/input/InputLibrary/getMouseState",
- "references/1.4.1/input/InputLibrary/getPressedKeys",
- "references/1.4.1/input/InputLibrary/getWheelState",
- "references/1.4.1/input/InputLibrary/isDragging",
- "references/1.4.1/input/InputLibrary/isKeyPressed"
- ],
- "root": "references/1.4.1/input/InputLibrary"
- }
- ]
- },
- {
- "dropdown": "Music",
- "pages": [
- "references/1.4.1/music/0-index",
- {
- "group": "MusicLibrary",
- "pages": [
- "references/1.4.1/music/MusicLibrary/load",
- "references/1.4.1/music/MusicLibrary/mute",
- "references/1.4.1/music/MusicLibrary/play"
- ],
- "root": "references/1.4.1/music/MusicLibrary"
- }
- ]
- },
- {
- "dropdown": "Network-Client",
- "pages": [
- "references/1.4.1/network-client/0-index",
- {
- "group": "NetworkClientLibrary",
- "pages": [
- "references/1.4.1/network-client/NetworkClientLibrary/tcp",
- "references/1.4.1/network-client/NetworkClientLibrary/udp"
- ],
- "root": "references/1.4.1/network-client/NetworkClientLibrary"
- },
- {
- "group": "TCPClient",
- "pages": [
- "references/1.4.1/network-client/TCPClient/connect",
- "references/1.4.1/network-client/TCPClient/constructor",
- "references/1.4.1/network-client/TCPClient/getReceivedPackets",
- "references/1.4.1/network-client/TCPClient/isConnected",
- "references/1.4.1/network-client/TCPClient/sendData"
- ],
- "root": "references/1.4.1/network-client/TCPClient"
- },
- {
- "group": "UDPClient",
- "pages": [
- "references/1.4.1/network-client/UDPClient/connect",
- "references/1.4.1/network-client/UDPClient/constructor",
- "references/1.4.1/network-client/UDPClient/getReceivedPackets",
- "references/1.4.1/network-client/UDPClient/isConnected",
- "references/1.4.1/network-client/UDPClient/sendData"
- ],
- "root": "references/1.4.1/network-client/UDPClient"
- }
- ]
- },
- {
- "dropdown": "Network-Server",
- "pages": [
- "references/1.4.1/network-server/0-index",
- {
- "group": "NetworkServerLibrary",
- "pages": [
- "references/1.4.1/network-server/NetworkServerLibrary/tcp",
- "references/1.4.1/network-server/NetworkServerLibrary/udp"
- ],
- "root": "references/1.4.1/network-server/NetworkServerLibrary"
- },
- {
- "group": "TCPServer",
- "pages": [
- "references/1.4.1/network-server/TCPServer/constructor",
- "references/1.4.1/network-server/TCPServer/getConnectedClients",
- "references/1.4.1/network-server/TCPServer/getReceivedPackets",
- "references/1.4.1/network-server/TCPServer/listen",
- "references/1.4.1/network-server/TCPServer/sendToClient",
- "references/1.4.1/network-server/TCPServer/sendToEverybody"
- ],
- "root": "references/1.4.1/network-server/TCPServer"
- },
- {
- "group": "UDPServer",
- "pages": [
- "references/1.4.1/network-server/UDPServer/constructor",
- "references/1.4.1/network-server/UDPServer/getConnectedClients",
- "references/1.4.1/network-server/UDPServer/getReceivedPackets",
- "references/1.4.1/network-server/UDPServer/listen",
- "references/1.4.1/network-server/UDPServer/sendToClient",
- "references/1.4.1/network-server/UDPServer/sendToEverybody"
- ],
- "root": "references/1.4.1/network-server/UDPServer"
- }
- ]
- },
- {
- "dropdown": "Sound",
- "pages": [
- "references/1.4.1/sound/0-index",
- {
- "group": "SoundLibrary",
- "pages": [
- "references/1.4.1/sound/SoundLibrary/load",
- "references/1.4.1/sound/SoundLibrary/mute",
- "references/1.4.1/sound/SoundLibrary/play"
- ],
- "root": "references/1.4.1/sound/SoundLibrary"
- }
- ]
- }
- ]
- },
- {
- "version": "1.3.0",
- "dropdowns": [
- {
- "dropdown": "Asset-Manager",
- "pages": [
- "references/1.3.0/asset-manager/index",
- {
- "group": "Asset-Manager",
- "pages": [
- {
- "group": "AssetManagerLibrary",
- "pages": [
- "references/1.3.0/asset-manager/asset-manager/AssetManagerLibrary/__init",
- "references/1.3.0/asset-manager/asset-manager/AssetManagerLibrary/__name",
- "references/1.3.0/asset-manager/asset-manager/AssetManagerLibrary/getAsset"
- ],
- "root": "references/1.3.0/asset-manager/asset-manager/AssetManagerLibrary"
- }
- ],
- "root": "references/1.3.0/asset-manager/asset-manager"
- }
- ]
- },
- {
- "dropdown": "Common",
- "pages": [
- "references/1.3.0/common/index",
- {
- "group": "Common",
- "pages": [
- {
- "group": "ApplicationContext",
- "pages": [
- "references/1.3.0/common/common/ApplicationContext/_delta",
- "references/1.3.0/common/common/ApplicationContext/delta",
- "references/1.3.0/common/common/ApplicationContext/isRunning",
- "references/1.3.0/common/common/ApplicationContext/muteSoundLibraries",
- "references/1.3.0/common/common/ApplicationContext/setIsRunning"
- ],
- "root": "references/1.3.0/common/common/ApplicationContext"
- },
- "references/1.3.0/common/common/ASSET_MANAGER_LIBRARY",
- {
- "group": "BaseAssetManagerLibrary",
- "pages": [
- "references/1.3.0/common/common/BaseAssetManagerLibrary/__init",
- "references/1.3.0/common/common/BaseAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.3.0/common/common/BaseAssetManagerLibrary"
- },
- {
- "group": "BaseComponentSystemLibrary",
- "pages": [
- "references/1.3.0/common/common/BaseComponentSystemLibrary/__run"
- ],
- "root": "references/1.3.0/common/common/BaseComponentSystemLibrary"
- },
- {
- "group": "BaseGraphicsLibrary",
- "pages": [
- "references/1.3.0/common/common/BaseGraphicsLibrary/__run"
- ],
- "root": "references/1.3.0/common/common/BaseGraphicsLibrary"
- },
- {
- "group": "BaseInputLibrary",
- "pages": [
- "references/1.3.0/common/common/BaseInputLibrary/__run"
- ],
- "root": "references/1.3.0/common/common/BaseInputLibrary"
- },
- {
- "group": "BaseMusicLibrary",
- "pages": [
- "references/1.3.0/common/common/BaseMusicLibrary/__init",
- "references/1.3.0/common/common/BaseMusicLibrary/mute",
- "references/1.3.0/common/common/BaseMusicLibrary/play"
- ],
- "root": "references/1.3.0/common/common/BaseMusicLibrary"
- },
- "references/1.3.0/common/common/BaseNetworkLibrary",
- {
- "group": "BaseSoundLibrary",
- "pages": [
- "references/1.3.0/common/common/BaseSoundLibrary/__init",
- "references/1.3.0/common/common/BaseSoundLibrary/mute",
- "references/1.3.0/common/common/BaseSoundLibrary/play"
- ],
- "root": "references/1.3.0/common/common/BaseSoundLibrary"
- },
- "references/1.3.0/common/common/ClearContext",
- {
- "group": "ClientLibraryManager",
- "pages": [
- "references/1.3.0/common/common/ClientLibraryManager/constructor",
- "references/1.3.0/common/common/ClientLibraryManager/get",
- "references/1.3.0/common/common/ClientLibraryManager/getAssetManager",
- "references/1.3.0/common/common/ClientLibraryManager/getComponentSystem",
- "references/1.3.0/common/common/ClientLibraryManager/getGraphics",
- "references/1.3.0/common/common/ClientLibraryManager/getInput",
- "references/1.3.0/common/common/ClientLibraryManager/getMusic",
- "references/1.3.0/common/common/ClientLibraryManager/getNetwork",
- "references/1.3.0/common/common/ClientLibraryManager/getSound"
- ],
- "root": "references/1.3.0/common/common/ClientLibraryManager"
- },
- "references/1.3.0/common/common/COMPONENT_SYSTEM_LIBRARY",
- {
- "group": "Context",
- "pages": [
- "references/1.3.0/common/common/Context/app",
- "references/1.3.0/common/common/Context/constructor",
- "references/1.3.0/common/common/Context/libs"
- ],
- "root": "references/1.3.0/common/common/Context"
- },
- "references/1.3.0/common/common/DefaultLibrariesEnum",
- "references/1.3.0/common/common/ExecutionContext",
- "references/1.3.0/common/common/GRAPHICS_LIBRARY",
- {
- "group": "IAssetManagerLibrary",
- "pages": [
- "references/1.3.0/common/common/IAssetManagerLibrary/getAsset"
- ],
- "root": "references/1.3.0/common/common/IAssetManagerLibrary"
- },
- "references/1.3.0/common/common/IComponentSystemLibrary",
- {
- "group": "IConfigRegistry",
- "pages": [
- "references/1.3.0/common/common/IConfigRegistry/registerConfig"
- ],
- "root": "references/1.3.0/common/common/IConfigRegistry"
- },
- "references/1.3.0/common/common/IExposedLibrary",
- "references/1.3.0/common/common/IGraphicsLibrary",
- "references/1.3.0/common/common/IInputLibrary",
- {
- "group": "ILibrary",
- "pages": [
- "references/1.3.0/common/common/ILibrary/__clear",
- "references/1.3.0/common/common/ILibrary/__init",
- "references/1.3.0/common/common/ILibrary/__name",
- "references/1.3.0/common/common/ILibrary/__relationship"
- ],
- "root": "references/1.3.0/common/common/ILibrary"
- },
- "references/1.3.0/common/common/IMusicLibrary",
- {
- "group": "IMutableLibrary",
- "pages": [
- "references/1.3.0/common/common/IMutableLibrary/mute"
- ],
- "root": "references/1.3.0/common/common/IMutableLibrary"
- },
- "references/1.3.0/common/common/INetworkLibrary",
- {
- "group": "InitContext",
- "pages": [
- "references/1.3.0/common/common/InitContext/config",
- "references/1.3.0/common/common/InitContext/constructor",
- "references/1.3.0/common/common/InitContext/container",
- "references/1.3.0/common/common/InitContext/env",
- "references/1.3.0/common/common/InitContext/files"
- ],
- "root": "references/1.3.0/common/common/InitContext"
- },
- "references/1.3.0/common/common/INPUT_LIBRARY",
- {
- "group": "IRunClientOptions",
- "pages": [
- "references/1.3.0/common/common/IRunClientOptions/container",
- "references/1.3.0/common/common/IRunClientOptions/env",
- "references/1.3.0/common/common/IRunClientOptions/files"
- ],
- "root": "references/1.3.0/common/common/IRunClientOptions"
- },
- {
- "group": "IRunnerLibrary",
- "pages": [
- "references/1.3.0/common/common/IRunnerLibrary/__run"
- ],
- "root": "references/1.3.0/common/common/IRunnerLibrary"
- },
- "references/1.3.0/common/common/IRunOptions",
- {
- "group": "IRunServerOptions",
- "pages": [
- "references/1.3.0/common/common/IRunServerOptions/env",
- "references/1.3.0/common/common/IRunServerOptions/files"
- ],
- "root": "references/1.3.0/common/common/IRunServerOptions"
- },
- "references/1.3.0/common/common/ISoundLibrary",
- {
- "group": "LibraryContext",
- "pages": [
- "references/1.3.0/common/common/LibraryContext/_status",
- "references/1.3.0/common/common/LibraryContext/status"
- ],
- "root": "references/1.3.0/common/common/LibraryContext"
- },
- {
- "group": "LibraryHandle",
- "pages": [
- "references/1.3.0/common/common/LibraryHandle/constructor",
- "references/1.3.0/common/common/LibraryHandle/context",
- "references/1.3.0/common/common/LibraryHandle/library",
- "references/1.3.0/common/common/LibraryHandle/symbol"
- ],
- "root": "references/1.3.0/common/common/LibraryHandle"
- },
- {
- "group": "LibraryManager",
- "pages": [
- "references/1.3.0/common/common/LibraryManager/constructor",
- "references/1.3.0/common/common/LibraryManager/getAssetManager",
- "references/1.3.0/common/common/LibraryManager/getComponentSystem",
- "references/1.3.0/common/common/LibraryManager/getGraphics",
- "references/1.3.0/common/common/LibraryManager/getInput",
- "references/1.3.0/common/common/LibraryManager/getMusic",
- "references/1.3.0/common/common/LibraryManager/getNetwork",
- "references/1.3.0/common/common/LibraryManager/getSound"
- ],
- "root": "references/1.3.0/common/common/LibraryManager"
- },
- "references/1.3.0/common/common/LibraryStatusEnum",
- "references/1.3.0/common/common/MUSIC_LIBRARY",
- "references/1.3.0/common/common/NETWORK_LIBRARY",
- {
- "group": "NfConfigException",
- "pages": [
- "references/1.3.0/common/common/NfConfigException/code",
- "references/1.3.0/common/common/NfConfigException/constructor"
- ],
- "root": "references/1.3.0/common/common/NfConfigException"
- },
- {
- "group": "NfFetchException",
- "pages": [
- "references/1.3.0/common/common/NfFetchException/code",
- "references/1.3.0/common/common/NfFetchException/constructor"
- ],
- "root": "references/1.3.0/common/common/NfFetchException"
- },
- {
- "group": "NfFile",
- "pages": [
- "references/1.3.0/common/common/NfFile/arrayBuffer",
- "references/1.3.0/common/common/NfFile/blob",
- "references/1.3.0/common/common/NfFile/bytes",
- "references/1.3.0/common/common/NfFile/constructor",
- "references/1.3.0/common/common/NfFile/formData",
- "references/1.3.0/common/common/NfFile/json",
- "references/1.3.0/common/common/NfFile/path",
- "references/1.3.0/common/common/NfFile/text"
- ],
- "root": "references/1.3.0/common/common/NfFile"
- },
- {
- "group": "NfNotFound",
- "pages": [
- "references/1.3.0/common/common/NfNotFound/code",
- "references/1.3.0/common/common/NfNotFound/constructor"
- ],
- "root": "references/1.3.0/common/common/NfNotFound"
- },
- {
- "group": "NfNotInitializedException",
- "pages": [
- "references/1.3.0/common/common/NfNotInitializedException/code",
- "references/1.3.0/common/common/NfNotInitializedException/constructor"
- ],
- "root": "references/1.3.0/common/common/NfNotInitializedException"
- },
- "references/1.3.0/common/common/SOUND_LIBRARY"
- ],
- "root": "references/1.3.0/common/common"
- }
- ]
- },
- {
- "dropdown": "Config",
- "pages": [
- "references/1.3.0/config/index",
- {
- "group": "Config",
- "pages": [
- "references/1.3.0/config/config/Default",
- "references/1.3.0/config/config/IsIpOrFQDN",
- "references/1.3.0/config/config/TransformToBoolean"
- ],
- "root": "references/1.3.0/config/config"
- }
- ]
- },
- {
- "dropdown": "Core",
- "pages": [
- "references/1.3.0/core/index",
- {
- "group": "Core",
- "pages": [
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.3.0/core/core/NanoforgeClient/useGraphics",
- "references/1.3.0/core/core/NanoforgeClient/useInput",
- "references/1.3.0/core/core/NanoforgeClient/useSound"
- ],
- "root": "references/1.3.0/core/core/NanoforgeClient"
- },
- "references/1.3.0/core/core/NanoforgeFactory",
- "references/1.3.0/core/core/NanoforgeServer"
- ],
- "root": "references/1.3.0/core/core"
- }
- ]
- },
- {
- "dropdown": "Core-Editor",
- "pages": [
- "references/1.3.0/core-editor/index",
- {
- "group": "Core-Editor",
- "pages": [
- {
- "group": "NanoforgeClient",
- "pages": [
- "references/1.3.0/core-editor/core-editor/NanoforgeClient/useGraphics",
- "references/1.3.0/core-editor/core-editor/NanoforgeClient/useInput",
- "references/1.3.0/core-editor/core-editor/NanoforgeClient/useSound"
- ],
- "root": "references/1.3.0/core-editor/core-editor/NanoforgeClient"
- },
- "references/1.3.0/core-editor/core-editor/NanoforgeFactory",
- "references/1.3.0/core-editor/core-editor/NanoforgeServer"
- ],
- "root": "references/1.3.0/core-editor/core-editor"
- }
- ]
- },
- {
- "dropdown": "ECS-Client",
- "pages": [
- "references/1.3.0/ecs-client/index",
- {
- "group": "ECS-Client",
- "pages": [
- {
- "group": "ECSClientLibrary",
- "pages": [
- "references/1.3.0/ecs-client/ecs-client/ECSClientLibrary/__init",
- "references/1.3.0/ecs-client/ecs-client/ECSClientLibrary/__name",
- "references/1.3.0/ecs-client/ecs-client/ECSClientLibrary/constructor"
- ],
- "root": "references/1.3.0/ecs-client/ecs-client/ECSClientLibrary"
- }
- ],
- "root": "references/1.3.0/ecs-client/ecs-client"
- }
- ]
- },
- {
- "dropdown": "ECS-Lib",
- "pages": [
- "references/1.3.0/ecs-lib/index",
- {
- "group": "ECS-Lib",
- "pages": [
- {
- "group": "AbstractECSLibrary",
- "pages": [
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/__name",
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/__run",
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/_registry",
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/constructor",
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/module",
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/path",
- "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary/registry"
- ],
- "root": "references/1.3.0/ecs-lib/ecs-lib/AbstractECSLibrary"
- },
- "references/1.3.0/ecs-lib/ecs-lib/Component",
- "references/1.3.0/ecs-lib/ecs-lib/EditorComponentManifest",
- "references/1.3.0/ecs-lib/ecs-lib/EditorSystemManifest",
- {
- "group": "Entity",
- "pages": [
- "references/1.3.0/ecs-lib/ecs-lib/Entity/getId"
- ],
- "root": "references/1.3.0/ecs-lib/ecs-lib/Entity"
- },
- {
- "group": "Registry",
- "pages": [
- "references/1.3.0/ecs-lib/ecs-lib/Registry/addComponent",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/addSystem",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/clearEntities",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/clearSystems",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/entityFromIndex",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/getComponents",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/getComponentsConst",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/getEntityComponent",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/getEntityComponentConst",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/getZipper",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/killEntity",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/maxEntities",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/registerComponent",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/removeComponent",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/removeSystem",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/runSystems",
- "references/1.3.0/ecs-lib/ecs-lib/Registry/spawnEntity"
- ],
- "root": "references/1.3.0/ecs-lib/ecs-lib/Registry"
- },
- {
- "group": "SparseArray",
- "pages": [
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/clear",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/empty",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/erase",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/get",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/getConst",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/getIndex",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/insertAt_1",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/insertAt",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/resize",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/set",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/setByCopy",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/setByMove",
- "references/1.3.0/ecs-lib/ecs-lib/SparseArray/size"
- ],
- "root": "references/1.3.0/ecs-lib/ecs-lib/SparseArray"
- },
- "references/1.3.0/ecs-lib/ecs-lib/System"
- ],
- "root": "references/1.3.0/ecs-lib/ecs-lib"
- }
- ]
- },
- {
- "dropdown": "ECS-Server",
- "pages": [
- "references/1.3.0/ecs-server/index",
- {
- "group": "ECS-Server",
- "pages": [
- {
- "group": "ECSServerLibrary",
- "pages": [
- "references/1.3.0/ecs-server/ecs-server/ECSServerLibrary/__init",
- "references/1.3.0/ecs-server/ecs-server/ECSServerLibrary/__name",
- "references/1.3.0/ecs-server/ecs-server/ECSServerLibrary/constructor"
- ],
- "root": "references/1.3.0/ecs-server/ecs-server/ECSServerLibrary"
- },
- "references/1.3.0/ecs-server/ecs-server/Module"
- ],
- "root": "references/1.3.0/ecs-server/ecs-server"
- }
- ]
- },
- {
- "dropdown": "Graphics-2d",
- "pages": [
- "references/1.3.0/graphics-2d/index",
- {
- "group": "Graphics-2d",
- "pages": [
- "references/1.3.0/graphics-2d/graphics-2d/_global",
- "references/1.3.0/graphics-2d/graphics-2d/_injectGlobal",
- "references/1.3.0/graphics-2d/graphics-2d/_mouseDblClickPointerId",
- "references/1.3.0/graphics-2d/graphics-2d/_mouseInDblClickWindow",
- "references/1.3.0/graphics-2d/graphics-2d/_mouseListenClick",
- "references/1.3.0/graphics-2d/graphics-2d/_pointerDblClickPointerId",
- "references/1.3.0/graphics-2d/graphics-2d/_pointerInDblClickWindow",
- "references/1.3.0/graphics-2d/graphics-2d/_pointerListenClick",
- "references/1.3.0/graphics-2d/graphics-2d/_renderBackend",
- "references/1.3.0/graphics-2d/graphics-2d/_touchDblClickPointerId",
- "references/1.3.0/graphics-2d/graphics-2d/_touchInDblClickWindow",
- "references/1.3.0/graphics-2d/graphics-2d/_touchListenClick",
- "references/1.3.0/graphics-2d/graphics-2d/angleDeg",
- "references/1.3.0/graphics-2d/graphics-2d/Animation_2",
- "references/1.3.0/graphics-2d/graphics-2d/Arc",
- "references/1.3.0/graphics-2d/graphics-2d/ArcConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Arrow",
- "references/1.3.0/graphics-2d/graphics-2d/ArrowConfig",
- "references/1.3.0/graphics-2d/graphics-2d/autoDrawEnabled",
- "references/1.3.0/graphics-2d/graphics-2d/Canvas",
- "references/1.3.0/graphics-2d/graphics-2d/capturePointerEventsEnabled",
- "references/1.3.0/graphics-2d/graphics-2d/Circle",
- "references/1.3.0/graphics-2d/graphics-2d/CircleConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Container",
- "references/1.3.0/graphics-2d/graphics-2d/ContainerConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Context",
- "references/1.3.0/graphics-2d/graphics-2d/dblClickWindow",
- "references/1.3.0/graphics-2d/graphics-2d/DD",
- "references/1.3.0/graphics-2d/graphics-2d/document_2",
- "references/1.3.0/graphics-2d/graphics-2d/dragButtons",
- "references/1.3.0/graphics-2d/graphics-2d/dragDistance",
- "references/1.3.0/graphics-2d/graphics-2d/Easings",
- "references/1.3.0/graphics-2d/graphics-2d/Ellipse",
- "references/1.3.0/graphics-2d/graphics-2d/EllipseConfig",
- "references/1.3.0/graphics-2d/graphics-2d/enableTrace",
- "references/1.3.0/graphics-2d/graphics-2d/FastLayer",
- "references/1.3.0/graphics-2d/graphics-2d/Filters",
- "references/1.3.0/graphics-2d/graphics-2d/getAngle",
- {
- "group": "Graphics2DLibrary",
- "pages": [
- "references/1.3.0/graphics-2d/graphics-2d/Graphics2DLibrary/__init",
- "references/1.3.0/graphics-2d/graphics-2d/Graphics2DLibrary/__name",
- "references/1.3.0/graphics-2d/graphics-2d/Graphics2DLibrary/__run",
- "references/1.3.0/graphics-2d/graphics-2d/Graphics2DLibrary/baseLayer",
- "references/1.3.0/graphics-2d/graphics-2d/Graphics2DLibrary/stage"
- ],
- "root": "references/1.3.0/graphics-2d/graphics-2d/Graphics2DLibrary"
- },
- "references/1.3.0/graphics-2d/graphics-2d/Group",
- "references/1.3.0/graphics-2d/graphics-2d/GroupConfig",
- "references/1.3.0/graphics-2d/graphics-2d/hitOnDragEnabled",
- "references/1.3.0/graphics-2d/graphics-2d/Image_2",
- "references/1.3.0/graphics-2d/graphics-2d/ImageConfig",
- "references/1.3.0/graphics-2d/graphics-2d/isBrowser",
- "references/1.3.0/graphics-2d/graphics-2d/isDragging",
- "references/1.3.0/graphics-2d/graphics-2d/isDragReady",
- "references/1.3.0/graphics-2d/graphics-2d/isTransforming",
- "references/1.3.0/graphics-2d/graphics-2d/isUnminified",
- "references/1.3.0/graphics-2d/graphics-2d/KonvaEventListener",
- "references/1.3.0/graphics-2d/graphics-2d/KonvaEventObject",
- "references/1.3.0/graphics-2d/graphics-2d/KonvaPointerEvent",
- "references/1.3.0/graphics-2d/graphics-2d/Label",
- "references/1.3.0/graphics-2d/graphics-2d/LabelConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Layer",
- "references/1.3.0/graphics-2d/graphics-2d/LayerConfig",
- "references/1.3.0/graphics-2d/graphics-2d/legacyTextRendering",
- "references/1.3.0/graphics-2d/graphics-2d/Line",
- "references/1.3.0/graphics-2d/graphics-2d/LineConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Node_2",
- "references/1.3.0/graphics-2d/graphics-2d/NodeConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Path",
- "references/1.3.0/graphics-2d/graphics-2d/PathConfig",
- "references/1.3.0/graphics-2d/graphics-2d/pixelRatio",
- "references/1.3.0/graphics-2d/graphics-2d/pointerEventsEnabled",
- "references/1.3.0/graphics-2d/graphics-2d/Rect",
- "references/1.3.0/graphics-2d/graphics-2d/RectConfig",
- "references/1.3.0/graphics-2d/graphics-2d/RegularPolygon",
- "references/1.3.0/graphics-2d/graphics-2d/RegularPolygonConfig",
- "references/1.3.0/graphics-2d/graphics-2d/releaseCanvasOnDestroy",
- "references/1.3.0/graphics-2d/graphics-2d/Ring",
- "references/1.3.0/graphics-2d/graphics-2d/RingConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Shape",
- "references/1.3.0/graphics-2d/graphics-2d/ShapeConfig",
- "references/1.3.0/graphics-2d/graphics-2d/shapes",
- "references/1.3.0/graphics-2d/graphics-2d/showWarnings",
- "references/1.3.0/graphics-2d/graphics-2d/Sprite",
- "references/1.3.0/graphics-2d/graphics-2d/SpriteConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Stage",
- "references/1.3.0/graphics-2d/graphics-2d/StageConfig",
- "references/1.3.0/graphics-2d/graphics-2d/stages",
- "references/1.3.0/graphics-2d/graphics-2d/Star",
- "references/1.3.0/graphics-2d/graphics-2d/StarConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Tag",
- "references/1.3.0/graphics-2d/graphics-2d/TagConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Text_2",
- "references/1.3.0/graphics-2d/graphics-2d/TextConfig",
- "references/1.3.0/graphics-2d/graphics-2d/TextPath",
- "references/1.3.0/graphics-2d/graphics-2d/TextPathConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Transform",
- "references/1.3.0/graphics-2d/graphics-2d/Transformer_2",
- "references/1.3.0/graphics-2d/graphics-2d/TransformerConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Tween",
- "references/1.3.0/graphics-2d/graphics-2d/TweenConfig",
- "references/1.3.0/graphics-2d/graphics-2d/Util",
- "references/1.3.0/graphics-2d/graphics-2d/Vector2d",
- "references/1.3.0/graphics-2d/graphics-2d/version",
- "references/1.3.0/graphics-2d/graphics-2d/Wedge",
- "references/1.3.0/graphics-2d/graphics-2d/WedgeConfig"
- ],
- "root": "references/1.3.0/graphics-2d/graphics-2d"
- }
- ]
- },
- {
- "dropdown": "Input",
- "pages": [
- "references/1.3.0/input/index",
- {
- "group": "Input",
- "pages": [
- "references/1.3.0/input/input/InputEnum",
- {
- "group": "InputLibrary",
- "pages": [
- "references/1.3.0/input/input/InputLibrary/__init",
- "references/1.3.0/input/input/InputLibrary/__name",
- "references/1.3.0/input/input/InputLibrary/__run",
- "references/1.3.0/input/input/InputLibrary/constructor",
- "references/1.3.0/input/input/InputLibrary/getDragState",
- "references/1.3.0/input/input/InputLibrary/getMousePosition",
- "references/1.3.0/input/input/InputLibrary/getMouseState",
- "references/1.3.0/input/input/InputLibrary/getPressedKeys",
- "references/1.3.0/input/input/InputLibrary/getWheelState",
- "references/1.3.0/input/input/InputLibrary/isDragging",
- "references/1.3.0/input/input/InputLibrary/isKeyPressed"
- ],
- "root": "references/1.3.0/input/input/InputLibrary"
- }
- ],
- "root": "references/1.3.0/input/input"
- }
- ]
- },
- {
- "dropdown": "Music",
- "pages": [
- "references/1.3.0/music/index",
- {
- "group": "Music",
- "pages": [
- {
- "group": "MusicLibrary",
- "pages": [
- "references/1.3.0/music/music/MusicLibrary/__init",
- "references/1.3.0/music/music/MusicLibrary/__name",
- "references/1.3.0/music/music/MusicLibrary/load",
- "references/1.3.0/music/music/MusicLibrary/mute",
- "references/1.3.0/music/music/MusicLibrary/play"
- ],
- "root": "references/1.3.0/music/music/MusicLibrary"
- }
- ],
- "root": "references/1.3.0/music/music"
- }
- ]
- },
- {
- "dropdown": "Network-Client",
- "pages": [
- "references/1.3.0/network-client/index",
- {
- "group": "Network-Client",
- "pages": [
- {
- "group": "NetworkClientLibrary",
- "pages": [
- "references/1.3.0/network-client/network-client/NetworkClientLibrary/__init",
- "references/1.3.0/network-client/network-client/NetworkClientLibrary/__name",
- "references/1.3.0/network-client/network-client/NetworkClientLibrary/tcp",
- "references/1.3.0/network-client/network-client/NetworkClientLibrary/udp"
- ],
- "root": "references/1.3.0/network-client/network-client/NetworkClientLibrary"
- },
- {
- "group": "TCPClient",
- "pages": [
- "references/1.3.0/network-client/network-client/TCPClient/connect",
- "references/1.3.0/network-client/network-client/TCPClient/constructor",
- "references/1.3.0/network-client/network-client/TCPClient/getReceivedPackets",
- "references/1.3.0/network-client/network-client/TCPClient/isConnected",
- "references/1.3.0/network-client/network-client/TCPClient/sendData"
- ],
- "root": "references/1.3.0/network-client/network-client/TCPClient"
- },
- {
- "group": "UDPClient",
- "pages": [
- "references/1.3.0/network-client/network-client/UDPClient/connect",
- "references/1.3.0/network-client/network-client/UDPClient/constructor",
- "references/1.3.0/network-client/network-client/UDPClient/getReceivedPackets",
- "references/1.3.0/network-client/network-client/UDPClient/isConnected",
- "references/1.3.0/network-client/network-client/UDPClient/sendData"
- ],
- "root": "references/1.3.0/network-client/network-client/UDPClient"
- }
- ],
- "root": "references/1.3.0/network-client/network-client"
- }
- ]
- },
- {
- "dropdown": "Network-Server",
- "pages": [
- "references/1.3.0/network-server/index",
- {
- "group": "Network-Server",
- "pages": [
- {
- "group": "NetworkServerLibrary",
- "pages": [
- "references/1.3.0/network-server/network-server/NetworkServerLibrary/__init",
- "references/1.3.0/network-server/network-server/NetworkServerLibrary/__name",
- "references/1.3.0/network-server/network-server/NetworkServerLibrary/tcp",
- "references/1.3.0/network-server/network-server/NetworkServerLibrary/udp"
- ],
- "root": "references/1.3.0/network-server/network-server/NetworkServerLibrary"
- },
- {
- "group": "TCPServer",
- "pages": [
- "references/1.3.0/network-server/network-server/TCPServer/constructor",
- "references/1.3.0/network-server/network-server/TCPServer/getConnectedClients",
- "references/1.3.0/network-server/network-server/TCPServer/getReceivedPackets",
- "references/1.3.0/network-server/network-server/TCPServer/listen",
- "references/1.3.0/network-server/network-server/TCPServer/sendToClient",
- "references/1.3.0/network-server/network-server/TCPServer/sendToEverybody"
- ],
- "root": "references/1.3.0/network-server/network-server/TCPServer"
- },
- {
- "group": "UDPServer",
- "pages": [
- "references/1.3.0/network-server/network-server/UDPServer/constructor",
- "references/1.3.0/network-server/network-server/UDPServer/getConnectedClients",
- "references/1.3.0/network-server/network-server/UDPServer/getReceivedPackets",
- "references/1.3.0/network-server/network-server/UDPServer/listen",
- "references/1.3.0/network-server/network-server/UDPServer/sendToClient",
- "references/1.3.0/network-server/network-server/UDPServer/sendToEverybody"
- ],
- "root": "references/1.3.0/network-server/network-server/UDPServer"
- }
- ],
- "root": "references/1.3.0/network-server/network-server"
- }
- ]
- },
- {
- "dropdown": "Sound",
- "pages": [
- "references/1.3.0/sound/index",
- {
- "group": "Sound",
- "pages": [
- {
- "group": "SoundLibrary",
- "pages": [
- "references/1.3.0/sound/sound/SoundLibrary/__init",
- "references/1.3.0/sound/sound/SoundLibrary/__name",
- "references/1.3.0/sound/sound/SoundLibrary/load",
- "references/1.3.0/sound/sound/SoundLibrary/mute",
- "references/1.3.0/sound/sound/SoundLibrary/play"
- ],
- "root": "references/1.3.0/sound/sound/SoundLibrary"
- }
- ],
- "root": "references/1.3.0/sound/sound"
- }
- ]
- }
- ]
+ "group": "Loader",
+ "pages": {
+ "$ref": "./docs/loader/navigation.json"
+ }
}
]
+ },
+ {
+ "dropdown": "Editor",
+ "icon": "pen-ruler",
+ "pages": {
+ "$ref": "./docs/editor/navigation.json"
+ }
+ }
+ ]
+ },
+ {
+ "tab": "Guides",
+ "dropdowns": [
+ {
+ "dropdown": "CLI",
+ "icon": "terminal",
+ "pages": {
+ "$ref": "./guides/cli/navigation.json"
+ }
}
]
+ },
+ {
+ "tab": "API reference",
+ "versions": {
+ "$ref": "./references/engine/navigation.json"
+ }
}
]
- }
-}
\ No newline at end of file
+ },
+ "redirects": [
+ {
+ "source": "/docs/cli/getting-started/1-introduction",
+ "destination": "/docs/cli/getting-started/introduction"
+ },
+ {
+ "source": "/docs/cli/getting-started/2-installation",
+ "destination": "/docs/cli/getting-started/installation"
+ },
+ {
+ "source": "/docs/cli/getting-started/3-quickstart",
+ "destination": "/docs/cli/getting-started/quickstart"
+ },
+ {
+ "source": "/docs/cli/getting-started/index",
+ "destination": "/docs/cli/getting-started/introduction"
+ },
+ {
+ "source": "/docs/cli/getting-started/usage",
+ "destination": "/docs/cli/getting-started/introduction"
+ },
+ {
+ "source": "/docs/cli/commands/1-overview",
+ "destination": "/docs/cli/commands/overview"
+ },
+ {
+ "source": "/docs/cli/configuration/1-configuration-file",
+ "destination": "/docs/cli/configuration/configuration-file"
+ },
+ {
+ "source": "/docs/cli/configuration/2-environment-variables",
+ "destination": "/docs/cli/configuration/environment-variables"
+ },
+ {
+ "source": "/docs/cli/schematics/1-overview",
+ "destination": "/docs/cli/schematics/overview"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/1-new",
+ "destination": "/docs/cli/commands/new"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/2-dev",
+ "destination": "/docs/cli/commands/dev"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/3-build",
+ "destination": "/docs/cli/commands/build"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/4-start",
+ "destination": "/docs/cli/commands/start"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/5-create",
+ "destination": "/docs/cli/commands/create"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/6-install",
+ "destination": "/docs/cli/commands/install"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/7-install",
+ "destination": "/docs/cli/commands/install"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/7-editor",
+ "destination": "/docs/cli/commands/editor"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/8-editor",
+ "destination": "/docs/cli/commands/editor"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/8-registry",
+ "destination": "/docs/cli/commands/registry"
+ },
+ {
+ "source": "/docs/cli/commands/2-commands/9-registry",
+ "destination": "/docs/cli/commands/registry"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/1-workspace",
+ "destination": "/docs/cli/schematics/workspace"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/2-project",
+ "destination": "/docs/cli/schematics/project"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/3-component",
+ "destination": "/docs/cli/schematics/component"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/4-system",
+ "destination": "/docs/cli/schematics/system"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/1-application",
+ "destination": "/docs/cli/schematics/overview"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/2-configuration",
+ "destination": "/docs/cli/schematics/overview"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/3-part-base",
+ "destination": "/docs/cli/schematics/overview"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/4-part-main",
+ "destination": "/docs/cli/schematics/overview"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/5-docker",
+ "destination": "/docs/cli/schematics/overview"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/6-component",
+ "destination": "/docs/cli/schematics/component"
+ },
+ {
+ "source": "/docs/cli/schematics/2-schematics/7-system",
+ "destination": "/docs/cli/schematics/system"
+ },
+ {
+ "source": "/docs/cli/loader/1-overview",
+ "destination": "/docs/loader/overview"
+ },
+ {
+ "source": "/docs/cli/loader/2-client",
+ "destination": "/docs/loader/client"
+ },
+ {
+ "source": "/docs/cli/loader/3-website",
+ "destination": "/docs/loader/website"
+ },
+ {
+ "source": "/docs/cli/loader/4-server",
+ "destination": "/docs/loader/server"
+ },
+ {
+ "source": "/guides/cli/cli/1-overview",
+ "destination": "/guides/cli/overview"
+ },
+ {
+ "source": "/guides/cli/cli/2-create-a-project",
+ "destination": "/guides/cli/create-a-project"
+ },
+ {
+ "source": "/guides/cli/cli/3-develop-locally",
+ "destination": "/guides/cli/develop-locally"
+ },
+ {
+ "source": "/guides/cli/cli/4-build-and-deploy",
+ "destination": "/guides/cli/build-and-deploy"
+ },
+ {
+ "source": "/guides/cli/cli/5-components-and-systems",
+ "destination": "/guides/cli/components-and-systems"
+ },
+ {
+ "source": "/guides/cli/cli/6-publish-a-package",
+ "destination": "/guides/cli/publish-a-package"
+ },
+ {
+ "source": "/references/1.3.0/:slug*",
+ "destination": "/"
+ },
+ {
+ "source": "/references/1.4.0/:slug*",
+ "destination": "/"
+ },
+ {
+ "source": "/references/1.4.1/:slug*",
+ "destination": "/"
+ },
+ {
+ "source": "/references/1.4.2/:slug*",
+ "destination": "/"
+ },
+ {
+ "source": "/docs/engine/getting-started/1-index",
+ "destination": "/docs/engine/getting-started/index"
+ },
+ {
+ "source": "/docs/engine/getting-started/how_to_use",
+ "destination": "/docs/engine/getting-started/how-to-use"
+ },
+ {
+ "source": "/docs/engine/registry/writing_web_assembly",
+ "destination": "/docs/engine/registry/writing-web-assembly"
+ },
+ {
+ "source": "/docs/cli/getting-started",
+ "destination": "/docs/cli/getting-started/introduction"
+ }
+ ]
+}
diff --git a/docs/cli/commands/2-commands/7-install.mdx b/docs/cli/commands/2-commands/7-install.mdx
deleted file mode 100644
index f08fccc..0000000
--- a/docs/cli/commands/2-commands/7-install.mdx
+++ /dev/null
@@ -1,46 +0,0 @@
----
-title: install / add
-description: Add components, systems, or libraries to your project
----
-
-import { Note } from "mintlify/components";
-
-## Overview
-
-`nf install` (aliased as `nf add`) pulls components, systems, or libraries from the NanoForge
-registry into your project. By default it installs components and systems for the client; use
-`--lib` for libraries and `--server` to target the server.
-
-## Usage
-
-```bash
-nf install [names...]
-```
-
-## Options
-
-| Option | Description |
-| ----------------------------- | ------------------------------------------------------------------ |
-| `[names...]` | Names of the components/systems/libraries to install. |
-| `-d, --directory ` | Working directory of the command. |
-| `-l, --lib` | Install a library instead of a component/system. Default: `false`. |
-| `-s, --server` | Install on the server instead of the client. Default: `false`. |
-
-## Examples
-
-**Install a component for the client:**
-
-```bash
-nf install my-org/health-bar
-```
-
-**Install a library on the server:**
-
-```bash
-nf add my-org/physics --lib --server
-```
-
-
- Installing from a private scope may require authentication. See the [registry
- commands](./9-registry) to log in first.
-
diff --git a/docs/cli/commands/2-commands/8-editor.mdx b/docs/cli/commands/2-commands/8-editor.mdx
deleted file mode 100644
index 4e752f4..0000000
--- a/docs/cli/commands/2-commands/8-editor.mdx
+++ /dev/null
@@ -1,39 +0,0 @@
----
-title: editor
-description: Launch the NanoForge visual editor
----
-
-## Overview
-
-`nf editor` starts the NanoForge editor - a visual environment for inspecting and authoring your
-game. When a project `path` is given, the editor opens that project; by default it then opens in
-your browser.
-
-## Usage
-
-```bash
-nf editor [path]
-```
-
-## Options
-
-| Option | Description |
-| ----------------------------- | --------------------------------------------------------------------------------------------- |
-| `[path]` | Path to the project to open in the editor. |
-| `-d, --directory ` | Working directory of the command. |
-| `--open` | Open the editor in the default web browser. Default: `true` when `path` is set, else `false`. |
-| `--no-open` | Do not open the editor in the browser. |
-
-## Examples
-
-**Open the editor for the current project:**
-
-```bash
-nf editor .
-```
-
-**Start the editor without opening a browser tab:**
-
-```bash
-nf editor --no-open
-```
diff --git a/docs/cli/commands/2-commands/9-registry.mdx b/docs/cli/commands/2-commands/9-registry.mdx
deleted file mode 100644
index bba7010..0000000
--- a/docs/cli/commands/2-commands/9-registry.mdx
+++ /dev/null
@@ -1,65 +0,0 @@
----
-title: registry
-description: Authenticate with and publish to the NanoForge registry
----
-
-## Overview
-
-These commands manage your relationship with the NanoForge registry: authenticating, then publishing
-or removing packages. Authentication can be **global** (default, stored for your user) or **local**
-(scoped to the current project) with `-l, --local`.
-
-## login
-
-Log in to the NanoForge registry.
-
-```bash
-nf login
-```
-
-| Option | Description |
-| ----------------------------- | ------------------------------------------------------ |
-| `-d, --directory ` | Working directory of the command. |
-| `-l, --local` | Log in only for the current project. Default: `false`. |
-| `-k, --api-key ` | API key for the NanoForge registry. |
-
-```bash
-nf login --api-key
-```
-
-## logout
-
-Log out from the NanoForge registry.
-
-```bash
-nf logout
-```
-
-| Option | Description |
-| ----------------------------- | ------------------------------------- |
-| `-d, --directory ` | Working directory of the command. |
-| `-l, --local` | Log out only for the current project. |
-
-## publish
-
-Publish a package to the NanoForge registry.
-
-```bash
-nf publish
-```
-
-| Option | Description |
-| ----------------------------- | --------------------------------- |
-| `-d, --directory ` | Working directory of the command. |
-
-## unpublish
-
-Unpublish a package from the NanoForge registry.
-
-```bash
-nf unpublish
-```
-
-| Option | Description |
-| ----------------------------- | --------------------------------- |
-| `-d, --directory ` | Working directory of the command. |
diff --git a/docs/cli/commands/2-commands/3-build.mdx b/docs/cli/commands/build.mdx
similarity index 84%
rename from docs/cli/commands/2-commands/3-build.mdx
rename to docs/cli/commands/build.mdx
index 930f210..7af6ac5 100644
--- a/docs/cli/commands/2-commands/3-build.mdx
+++ b/docs/cli/commands/build.mdx
@@ -7,7 +7,10 @@ description: Build your NanoForge project for production
`nf build` compiles your NanoForge project. The client and server entry points, static directories,
and output directories all default to the values in your
-[configuration file](../../configuration/1-configuration-file) and can be overridden per run.
+[configuration file](/docs/cli/configuration/configuration-file) and can be overridden per run.
+
+When the workspace sets `network: "p2p"`, each server app is also built for the browser, into the
+client's output directory under `server/`, so the host player's tab can run it.
## Usage
diff --git a/docs/cli/commands/2-commands/5-create.mdx b/docs/cli/commands/create.mdx
similarity index 51%
rename from docs/cli/commands/2-commands/5-create.mdx
rename to docs/cli/commands/create.mdx
index e63ebcf..0f8751b 100644
--- a/docs/cli/commands/2-commands/5-create.mdx
+++ b/docs/cli/commands/create.mdx
@@ -1,6 +1,6 @@
---
title: create
-description: Create a NanoForge component or system
+description: Create a NanoForge component, system or editor plugin
---
## Overview
@@ -14,18 +14,19 @@ creates files for the client; pass `--server` to target the server instead.
nf create
```
-`` is either `component` or `system`.
+`` is `component`, `system`, or `plugin` (an editor plugin, a project of its own).
## Options
-| Option | Description |
-| ----------------------------- | ------------------------------------------------------------- |
-| `` | The type to create: `component` or `system`. |
-| `-d, --directory ` | Working directory of the command. |
-| `-c, --config ` | Path to the configuration file. |
-| `-n, --name ` | Name of the component or system. |
-| `-s, --server` | Create on the server instead of the client. Default: `false`. |
-| `-p, --path ` | Path to the component/system folder. |
+| Option | Description |
+| ----------------------------- | --------------------------------------------------------------- |
+| `` | The type to create: `component`, `system` or `plugin`. |
+| `-d, --directory ` | Working directory of the command. |
+| `-c, --config ` | Path to the configuration file. |
+| `-n, --name ` | Name of the component or system. |
+| `-s, --server` | Create on the server instead of the client. Default: `false`. |
+| `-p, --path ` | Path to the component/system folder, or the plugin's folder. |
+| `-t, --template ` | Plugins: `panel` (default) or `theme` (a color theme, no code). |
## Examples
@@ -40,3 +41,17 @@ nf create component --name Position
```bash
nf create system --name Movement --server
```
+
+**Create an editor plugin:**
+
+```bash
+nf create plugin --name @acme/score-board
+```
+
+**Create an editor theme** (a manifest with a color theme and an icon, no code):
+
+```bash
+nf create plugin --name @acme/forest --template theme
+cd forest && node build.mjs --watch
+DEV_PLUGINS=$(pwd) nf editor ../my-game # in another terminal: the editor reloads the theme
+```
diff --git a/docs/cli/commands/2-commands/2-dev.mdx b/docs/cli/commands/dev.mdx
similarity index 100%
rename from docs/cli/commands/2-commands/2-dev.mdx
rename to docs/cli/commands/dev.mdx
diff --git a/docs/cli/commands/2-commands/7-editor.mdx b/docs/cli/commands/editor.mdx
similarity index 100%
rename from docs/cli/commands/2-commands/7-editor.mdx
rename to docs/cli/commands/editor.mdx
diff --git a/docs/cli/commands/2-commands/6-install.mdx b/docs/cli/commands/install.mdx
similarity index 93%
rename from docs/cli/commands/2-commands/6-install.mdx
rename to docs/cli/commands/install.mdx
index f08fccc..42c131b 100644
--- a/docs/cli/commands/2-commands/6-install.mdx
+++ b/docs/cli/commands/install.mdx
@@ -3,8 +3,6 @@ title: install / add
description: Add components, systems, or libraries to your project
---
-import { Note } from "mintlify/components";
-
## Overview
`nf install` (aliased as `nf add`) pulls components, systems, or libraries from the NanoForge
@@ -42,5 +40,5 @@ nf add my-org/physics --lib --server
Installing from a private scope may require authentication. See the [registry
- commands](./9-registry) to log in first.
+ commands](/docs/cli/commands/registry) to log in first.
diff --git a/docs/cli/commands/2-commands/1-new.mdx b/docs/cli/commands/new.mdx
similarity index 100%
rename from docs/cli/commands/2-commands/1-new.mdx
rename to docs/cli/commands/new.mdx
diff --git a/docs/cli/commands/1-overview.mdx b/docs/cli/commands/overview.mdx
similarity index 66%
rename from docs/cli/commands/1-overview.mdx
rename to docs/cli/commands/overview.mdx
index 4d3915f..4e46496 100644
--- a/docs/cli/commands/1-overview.mdx
+++ b/docs/cli/commands/overview.mdx
@@ -3,8 +3,6 @@ title: Commands
description: Overview of every NanoForge CLI command
---
-import { Card, CardGroup } from "mintlify/components";
-
## Using the CLI
Every command follows the same shape:
@@ -24,28 +22,28 @@ nf --help
## Available commands
-
+
Scaffold a brand new NanoForge project.
-
+
Run your project in development mode with watching.
-
+
Compile your client and server for production.
-
+
Serve a built project, optionally over HTTPS.
-
+
Create a single component or system.
-
+
Add components, systems, or libraries from the registry.
-
+
Launch the NanoForge visual editor.
-
+
Authenticate, publish, and unpublish packages.
diff --git a/docs/cli/commands/2-commands/8-registry.mdx b/docs/cli/commands/registry.mdx
similarity index 100%
rename from docs/cli/commands/2-commands/8-registry.mdx
rename to docs/cli/commands/registry.mdx
diff --git a/docs/cli/commands/2-commands/4-start.mdx b/docs/cli/commands/start.mdx
similarity index 85%
rename from docs/cli/commands/2-commands/4-start.mdx
rename to docs/cli/commands/start.mdx
index cf1f49e..ae89a0f 100644
--- a/docs/cli/commands/2-commands/4-start.mdx
+++ b/docs/cli/commands/start.mdx
@@ -3,8 +3,6 @@ title: start
description: Start a built NanoForge project
---
-import { Note } from "mintlify/components";
-
## Overview
`nf start` serves a previously built NanoForge project. It launches the loader (the website that
@@ -47,5 +45,11 @@ nf start --cert ./certs/cert.pem --key ./certs/key.pem
Environment variables (for example server addresses and ports) are read from a `.env` file at the
project root when the game starts. See [Environment
- variables](../../configuration/2-environment-variables).
+ variables](/docs/cli/configuration/environment-variables).
+
+
+
+ When the workspace sets `network: "p2p"`, `nf start` adds `NANOFORGE_NETWORK_MODE=p2p` to the
+ environment of both apps: the server app only pairs players, and the game runs in the host
+ player's browser.
diff --git a/docs/cli/configuration/1-configuration-file.mdx b/docs/cli/configuration/configuration-file.mdx
similarity index 78%
rename from docs/cli/configuration/1-configuration-file.mdx
rename to docs/cli/configuration/configuration-file.mdx
index 51a89b9..74aa7e6 100644
--- a/docs/cli/configuration/1-configuration-file.mdx
+++ b/docs/cli/configuration/configuration-file.mdx
@@ -3,8 +3,6 @@ title: Configuration file
description: The nanoforge.config.ts (or .js) file consumed by the CLI
---
-import { Tooltip } from "mintlify/components";
-
## Overview
Every NanoForge workspace, project, or lib has a `nanoforge.config.ts` (or `.js`) at its root,
@@ -48,9 +46,10 @@ export default defineConfig({
## `workspace`
-| Field | Type | Default | Description |
-| ---------- | ---------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `packages` | `string[]` | `[]` | Glob patterns matched against directories relative to the workspace root, each expected to hold its own `client`, `server`, or `lib` config. |
+| Field | Type | Default | Description |
+| ---------- | ---------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `packages` | `string[]` | `[]` | Glob patterns matched against directories relative to the workspace root, each expected to hold its own `client`, `server`, or `lib` config. |
+| `network` | `"dedicated" \| "p2p"` | `"dedicated"` | Where the server app runs. `"p2p"` runs it in the browser of the first player who opens the game, the others joining that player over WebRTC: see [Peer-to-peer](#peer-to-peer). |
A directory matched by a pattern but missing a `nanoforge.config.ts`/`.js` is skipped without
error. A pattern that matches no project or lib at all only logs a warning, rather than failing
@@ -67,6 +66,27 @@ export default defineConfig({
});
```
+### Peer-to-peer
+
+With `network: "p2p"`, the same client and server apps run without a game server:
+
+- `nf build` also builds each server app for the browser, into the client's output (`server/`).
+- `nf start` sets `NANOFORGE_NETWORK_MODE=p2p` for both apps. The server process then only pairs
+ players (WebRTC signaling) on its `LISTENING_TCP_PORT`, and the environment stays the same as
+ with a dedicated server.
+- A player who opens the game without `?room=` hosts it in their tab, and the game can show its
+ invite link (`ctx.network.inviteLink`).
+
+```ts
+import { defineConfig } from "@nanoforge-dev/config";
+
+export default defineConfig({
+ type: "workspace",
+ packages: ["apps/*"],
+ network: "p2p",
+});
+```
+
## `lib`
| Field | Type | Default | Description |
diff --git a/docs/cli/configuration/2-environment-variables.mdx b/docs/cli/configuration/environment-variables.mdx
similarity index 96%
rename from docs/cli/configuration/2-environment-variables.mdx
rename to docs/cli/configuration/environment-variables.mdx
index 74991af..00b27e4 100644
--- a/docs/cli/configuration/2-environment-variables.mdx
+++ b/docs/cli/configuration/environment-variables.mdx
@@ -3,8 +3,6 @@ title: Environment variables
description: Pass configuration to the client and server at runtime
---
-import { Note } from "mintlify/components";
-
## Overview
When running a NanoForge game (via `nf start`), environment variables can be passed to the client
diff --git a/docs/cli/getting-started/index.mdx b/docs/cli/getting-started/index.mdx
deleted file mode 100644
index 609b2a6..0000000
--- a/docs/cli/getting-started/index.mdx
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: CLI
----
-
-# CLI
-
-The nanoforge CLI is the main tool to use when building or deploying a NanoForge application.
-
-To install the NanoForge CLI use:
-
-```bash
-npm install -g @nanoforge-dev/cli
-```
-
-For usage information see [Usage](./usage.mdx).
diff --git a/docs/cli/getting-started/2-installation.mdx b/docs/cli/getting-started/installation.mdx
similarity index 85%
rename from docs/cli/getting-started/2-installation.mdx
rename to docs/cli/getting-started/installation.mdx
index 1bdbbb8..3600f17 100644
--- a/docs/cli/getting-started/2-installation.mdx
+++ b/docs/cli/getting-started/installation.mdx
@@ -3,8 +3,6 @@ title: Installation
description: Install the NanoForge CLI and verify your setup
---
-import { Tab, Tabs } from "mintlify/components";
-
## Requirements
- **Node.js** 20 or later
@@ -37,4 +35,4 @@ nf new --help
## Next steps
-Continue to the [Quickstart](./3-quickstart) to create and run your first project.
+Continue to the [Quickstart](/docs/cli/getting-started/quickstart) to create and run your first project.
diff --git a/docs/cli/getting-started/1-introduction.mdx b/docs/cli/getting-started/introduction.mdx
similarity index 67%
rename from docs/cli/getting-started/1-introduction.mdx
rename to docs/cli/getting-started/introduction.mdx
index 6616b17..4fbb061 100644
--- a/docs/cli/getting-started/1-introduction.mdx
+++ b/docs/cli/getting-started/introduction.mdx
@@ -3,8 +3,6 @@ title: Introduction
description: What the NanoForge CLI is and what you can do with it
---
-import { Card, CardGroup } from "mintlify/components";
-
## What is the NanoForge CLI?
The NanoForge CLI (`nf`) is the main entry point for building, running, and deploying games made
@@ -17,24 +15,24 @@ production, and publishing reusable packages to the NanoForge registry.
## What can it do?
-
+
Create a fully configured project - client, optional server, linting, and Docker - in one
command.
-
+
Run your game locally with hot reloading, then start it as you would in production.
-
+
Publish and consume components, systems, and libraries through the NanoForge registry.
## Where to go next
-- New to NanoForge? Start with [Installation](./2-installation) then the
- [Quickstart](./3-quickstart).
-- Looking for a specific flag? See the [Commands reference](../commands/1-overview).
-- Want a task-oriented walkthrough? Browse the [Guides](../../guides/cli/1-overview).
+- New to NanoForge? Start with [Installation](/docs/cli/getting-started/installation) then the
+ [Quickstart](/docs/cli/getting-started/quickstart).
+- Looking for a specific flag? See the [Commands reference](/docs/cli/commands/overview).
+- Want a task-oriented walkthrough? Browse the [Guides](/guides/cli/overview).
See the [changelog](https://github.com/NanoForge-dev/CLI/blob/main/CHANGELOG.md) for the full
release history.
diff --git a/docs/cli/getting-started/3-quickstart.mdx b/docs/cli/getting-started/quickstart.mdx
similarity index 77%
rename from docs/cli/getting-started/3-quickstart.mdx
rename to docs/cli/getting-started/quickstart.mdx
index be335af..57f69d3 100644
--- a/docs/cli/getting-started/3-quickstart.mdx
+++ b/docs/cli/getting-started/quickstart.mdx
@@ -3,8 +3,6 @@ title: Quickstart
description: Create, run, and build your first NanoForge project
---
-import { Step, Steps } from "mintlify/components";
-
This quickstart takes you from an empty folder to a running game in a few minutes.
@@ -30,7 +28,7 @@ This quickstart takes you from an empty folder to a running game in a few minute
```
The scaffolder generates a `nanoforge.config.json` at the root. See
- [Configuration](../configuration/1-configuration-file) for what every field means.
+ [Configuration](/docs/cli/configuration/configuration-file) for what every field means.
@@ -59,5 +57,5 @@ This quickstart takes you from an empty folder to a running game in a few minute
## Where to go next
-- Learn each command in detail in the [Commands reference](../commands/1-overview).
-- Follow task-oriented [Guides](/guides/cli/1-overview) for common workflows.
+- Learn each command in detail in the [Commands reference](/docs/cli/commands/overview).
+- Follow task-oriented [Guides](/guides/cli/overview) for common workflows.
diff --git a/docs/cli/getting-started/usage.mdx b/docs/cli/getting-started/usage.mdx
deleted file mode 100644
index 2e0b36f..0000000
--- a/docs/cli/getting-started/usage.mdx
+++ /dev/null
@@ -1,179 +0,0 @@
----
-title: Usage
----
-
-# Usage
-
-## Creating a new project
-
-In order to create a new project you need to run:
-
-```bash
-nf new
-```
-
-## Commands
-
-Multiple commands exist in the CLI:
-
-- [build](#build)
-- [create](#create)
-- [dev](#dev)
-- [editor](#editor)
-- [generate](#generate)
-- [install/add](#install/add)
-- [login](#login)
-- [logout](#logout)
-- [new](#new)
-- [publish](#publish)
-- [start](#start)
-- [unpublish](#unpublish)
-
-## build
-
-Used to build your nanoforge project.
-
-- `-d, --directory ` specify the working directory of the command.
-- `-c, --config ` path to the config file. ([Schema](./config.schema.json))
-- `--client-entry ` specify the entry file of the client.
-- `--server-entry ` specify the entry file of the server.
-- `--client-static-dir ` specify the static directory of the client.
-- `--server-static-dir ` specify the static directory of the server.
-- `--client-out-dir ` specify the output directory of the client.
-- `--server-out-dir ` specify the output directory of the server.
-- `--editor` build with editor config.
-- `--watch` build app in watching mode. (default: `false`)
-
-## create
-
-Used to create nanoforge components or systems.
-
-- `` the type to create (component or system).
-- `-d, --directory ` specify the working directory of the command.
-- `-c, --config ` path to the config file. ([Schema](./config.schema.json))
-- `-n, --name ` name of the component/system.
-- `-s, --server` create on server instead of client. (default: `false`)
-- `-p, --path ` path to the component/system folder.
-
-## dev
-
-Used to run your nanoforge project in dev mode.
-
-- `-d, --directory ` specify the working directory of the command.
-- `-c, --config ` path to the config file. ([Schema](./config.schema.json))
-- `--generate` generate app files from config, like generate command in dev mode. (default: `false`)
-
-## editor
-
-Used to start the nanoforge editor.
-
-- `[path]` path to the project to open in the editor.
-- `-d, --directory ` specify the working directory of the command.
-- `--open` open the editor in the default web browser (default: `true` if path is specified, `false` otherwise).
-- `--no-open` do not open the editor in the default web browser.
-
-## generate
-
-Used to generate nanoforge project files from config.
-
-- `-d, --directory ` specify the working directory of the command.
-- `-c, --config ` path to the config file. ([Schema](./config.schema.json))
-- `--editor` generate the editor main file.
-- `--watch` generate app in watching mode. (default: `false`)
-
-## install/add
-
-Used to add nanoforge components, systems or libraries to your project.
-
-- `[names...]` names of the components/systems/libraries to install.
-- `-d, --directory ` specify the working directory of the command.
-- `-l, --lib` install a library instead of a component/system. (default: `false`)
-- `-s, --server` install on server instead of client. (default: `false`)
-
-## login
-
-Used to log in to the Nanoforge registry.
-
-- `-d, --directory ` specify the working directory of the command.
-- `-l, --local` log in only for the current project. (default: `false`)
-- `-k, --api-key ` API key for the Nanoforge registry.
-
-## logout
-
-Used to log out from the Nanoforge registry.
-
-- `-d, --directory ` specify the working directory of the command.
-- `-l, --local` log out only for the current project.
-
-## new
-
-Used to create a new nanoforge project.
-
-- `-d, --directory ` specify the working directory of the command.
-- `--name ` specify the name of your project.
-- `--path ` specify the relative path where your project will be created (default: name of the project).
-- `--package-manager ` specify the package manager of your project.
-- `--language ` specify the language of your project.
-- `--strict` use strict mode.
-- `--no-strict` do not use strict mode.
-- `--server` create a server.
-- `--no-server` do not create a server.
-- `--init-functions` initialize functions.
-- `--no-init-functions` do not initialize functions.
-- `--skip-install` skip installing dependencies.
-- `--no-skip-install` do not skip installing dependencies.
-- `--docker` generate docker files.
-- `--no-docker` do not generate docker files.
-- `--no-lint` do not generate lint files.
-- `--editor` add editor dependencies.
-- `--git` generate a git repository.
-- `--no-git` do not generate a git repository.
-- `--git-remote ` set up a git remote (required if `--git` is used).
-- `--no-git-remote` do not set up a git remote.
-
-## publish
-
-Used to publish a package to the Nanoforge registry.
-
-- `-d, --directory ` specify the working directory of the command.
-
-## start
-
-Used to start your nanoforge project.
-
-- `-d, --directory ` specify the working directory of the command.
-- `-c, --config ` path to the config file (default: "nanoforge.config.json"). ([Schema](./config.schema.json))
-- `-p, --port ` specify the port of the loader (the website to load the game).
-- `--client-dir ` specify the directory of the client.
-- `--server-dir ` specify the directory of the server.
-- `--watch` run app in watching mode. (default: `false`)
-- `--cert ` path to the SSL certificate for HTTPS.
-- `--key ` path to the SSL key for HTTPS.
-
-## unpublish
-
-Used to unpublish a package from the Nanoforge registry.
-
-- `-d, --directory ` specify the working directory of the command.
-
-## Environment Variables
-
-When running a NanoForge game (via `nf start`), environment variables can be passed to the client and server applications through a `.env` file at the root of the project or directly in the environment.
-
-```dotenv
-NANOFORGE_CLIENT_SERVER_TCP_PORT=4445
-NANOFORGE_CLIENT_SERVER_UDP_PORT=4444
-NANOFORGE_CLIENT_SERVER_ADDRESS=127.0.0.1
-```
-
-Variables are scoped by prefix:
-
-| Prefix | Availability |
-| ------------------- | ----------------------------------- |
-| `NANOFORGE_CLIENT_` | Available in the client only |
-| `NANOFORGE_SERVER_` | Available in the server only |
-| `NANOFORGE_` | Available in both client and server |
-
-> **Note:** Prefixes are stripped before the variable is exposed to libraries.
-
-For full documentation on how libraries consume these variables, see `@nanoforge-dev/config `\_\_.
diff --git a/docs/cli/navigation.json b/docs/cli/navigation.json
new file mode 100644
index 0000000..4b1ca16
--- /dev/null
+++ b/docs/cli/navigation.json
@@ -0,0 +1,45 @@
+[
+ {
+ "group": "Getting started",
+ "icon": "rocket",
+ "pages": [
+ "docs/cli/getting-started/introduction",
+ "docs/cli/getting-started/installation",
+ "docs/cli/getting-started/quickstart"
+ ]
+ },
+ {
+ "group": "Commands",
+ "icon": "terminal",
+ "pages": [
+ "docs/cli/commands/overview",
+ "docs/cli/commands/new",
+ "docs/cli/commands/dev",
+ "docs/cli/commands/build",
+ "docs/cli/commands/start",
+ "docs/cli/commands/create",
+ "docs/cli/commands/install",
+ "docs/cli/commands/editor",
+ "docs/cli/commands/registry"
+ ]
+ },
+ {
+ "group": "Configuration",
+ "icon": "sliders",
+ "pages": [
+ "docs/cli/configuration/configuration-file",
+ "docs/cli/configuration/environment-variables"
+ ]
+ },
+ {
+ "group": "Schematics",
+ "icon": "shapes",
+ "pages": [
+ "docs/cli/schematics/overview",
+ "docs/cli/schematics/workspace",
+ "docs/cli/schematics/project",
+ "docs/cli/schematics/component",
+ "docs/cli/schematics/system"
+ ]
+ }
+]
diff --git a/docs/cli/schematics/2-schematics/1-application.mdx b/docs/cli/schematics/2-schematics/1-application.mdx
deleted file mode 100644
index 9554bc3..0000000
--- a/docs/cli/schematics/2-schematics/1-application.mdx
+++ /dev/null
@@ -1,80 +0,0 @@
----
-title: Application
-description: Generate a complete NanoForge application scaffold
----
-
-import { ToolTip } from "mintlify/components";
-
-## Overview
-
-The `application` schematic creates a fully structured NanoForge project with all the base files needed to start development — `package.json`, linting configuration, TypeScript or JavaScript setup, and optionally `.env` for server-enabled apps.
-
-## Usage
-
-```bash
-nf new
-```
-
-Or via Angular DevKit schematics directly:
-
-```bash
-schematics @nanoforge-dev/schematics:application --name=my-app
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| ---------------- | ------------------------------------ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `name` | `string` | `nanoforge-app` | The name of the application |
-| `version` | `string` | `0.0.0` | Initial version in `package.json` |
-| `author` | `string` | `""` | Author field in `package.json` |
-| `description` | `string` | `""` | Description field in `package.json` |
-| `directory` | `string` | `name` | Destination directory for the generated files |
-| `language` | `"ts" \| "js"` | `ts` | Language to use for generated source files |
-| `strict` | `boolean` | `true` | Enable strict mode |
-| `lint` | `boolean` | `true` | Generate linting configuration files |
-| `packageManager` | `"npm" \| "yarn" \| "pnpm" \| "bun"` | `npm` | Package manager to target in scripts and lockfile references |
-| `server` | `boolean` | `false` | Configure a server for the application |
-| `editor` | `boolean` | `false` | Include editor dependencies |
-| `initFunctions` | `boolean` | `false` | Add init function lifecycle hooks |
-
-## Generated structure
-
-```
-my-app/
-├── package.json
-├── tsconfig.json # TypeScript only
-├── jsconfig.json # JavaScript only
-├── eslint.config.js # if lint: true
-├── prettier.config.js # if lint: true
-├── .prettierignore # if lint: true
-├── .env # if server: true
-├── .gitignore
-└── README.md
-```
-
-## Examples
-
-**Minimal TypeScript app:**
-
-```bash
-schematics @nanoforge-dev/schematics:application --name=my-game
-```
-
-**JavaScript app with pnpm and server:**
-
-```bash
-schematics @nanoforge-dev/schematics:application \
- --name=my-game \
- --language=js \
- --packageManager=pnpm \
- --server=true
-```
-
-**TypeScript app without linting:**
-
-```bash
-schematics @nanoforge-dev/schematics:application \
- --name=my-game \
- --lint=false
-```
diff --git a/docs/cli/schematics/2-schematics/2-configuration.mdx b/docs/cli/schematics/2-schematics/2-configuration.mdx
deleted file mode 100644
index 8514f09..0000000
--- a/docs/cli/schematics/2-schematics/2-configuration.mdx
+++ /dev/null
@@ -1,50 +0,0 @@
----
-title: Configuration
-description: Generate a NanoForge configuration file
----
-
-import { Tooltip } from "mintlify/components";
-
-## Overview
-
-The `configuration` schematic creates a `nanoforge.config.json` file at the root of your project. This file is the central configuration consumed by the NanoForge CLI for builds, starts, and other operations.
-
-## Usage
-
-```bash
-schematics @nanoforge-dev/schematics:configuration
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| --------------- | -------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `name` | `string` | `nanoforge-app` | The name of the application |
-| `directory` | `string` | `.` | Destination directory |
-| `server` | `boolean` | `false` | Include server configuration |
-| `language` | `"ts" \| "js"` | `ts` | Language used in the project |
-| `initFunctions` | `boolean` | `false` | Reference init functions in configuration |
-
-## Generated file
-
-```
-nanoforge.config.json
-```
-
-The generated file is an empty JSON object `{}` that you populate with the fields the NanoForge CLI expects. Refer to the [CLI documentation](https://github.com/NanoForge-dev/CLI) for the full list of supported fields.
-
-## Examples
-
-**Generate configuration at the project root:**
-
-```bash
-schematics @nanoforge-dev/schematics:configuration --name=my-game
-```
-
-**Generate configuration for a server-enabled project:**
-
-```bash
-schematics @nanoforge-dev/schematics:configuration \
- --name=my-game \
- --server=true
-```
diff --git a/docs/cli/schematics/2-schematics/3-part-base.mdx b/docs/cli/schematics/2-schematics/3-part-base.mdx
deleted file mode 100644
index eec16aa..0000000
--- a/docs/cli/schematics/2-schematics/3-part-base.mdx
+++ /dev/null
@@ -1,115 +0,0 @@
----
-title: Part Base
-description: Generate the base structure for a NanoForge client or server part
----
-
-import { Tooltip } from "mintlify/components";
-
-## Overview
-
-The `part-base` schematic generates the foundational folder structure for a NanoForge **client** or **server** part. It creates example components and systems, the `.nanoforge` save file used to track ECS state, and optionally lifecycle init functions.
-
-## Usage
-
-```bash
-schematics @nanoforge-dev/schematics:part-base --part=client
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| --------------- | ---------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `part` | `"client" \| "server"` | _(required)_ | The part of the application to generate |
-| `directory` | `string` | `.` | Destination directory for the generated files |
-| `language` | `"ts" \| "js"` | `ts` | Language to use for generated source files |
-| `server` | `boolean` | `false` | Whether the application has a server |
-| `initFunctions` | `boolean` | `false` | Add lifecycle init function hooks |
-
-## Generated structure
-
-```
-{directory}/
-├── {part}/
-│ ├── components/
-│ │ └── example.component.ts
-│ ├── systems/
-│ │ └── example.system.ts
-│ └── init/ # if initFunctions: true
-│ ├── before-init.ts
-│ ├── after-init.ts
-│ ├── before-registry-init.ts
-│ ├── after-registry-init.ts
-│ ├── before-run.ts
-│ └── after-run.ts
-└── .nanoforge/
- └── {part}.save.json
-```
-
-## Save file
-
-The `.nanoforge/{part}.save.json` file is the source of truth for ECS state. It lists the libraries, components, systems, and entities registered for this part. The `part-main` schematic reads this file to generate the `main.ts` entry point.
-
-```json
-{
- "libraries": [ ... ],
- "components": [
- {
- "name": "ExampleComponent",
- "path": "./components/example.component.ts",
- "paramsNames": ["paramA", "paramB", "paramC"]
- }
- ],
- "systems": [
- {
- "name": "exampleSystem",
- "path": "./systems/example.system.ts"
- }
- ],
- "entities": [
- {
- "id": "exampleEntity",
- "components": {
- "ExampleComponent": { "paramA": "example", "paramB": 10 }
- }
- }
- ]
-}
-```
-
-## Init functions
-
-When `initFunctions` is `true`, the following lifecycle hooks are scaffolded:
-
-| File | Hook | Called |
-| ------------------------- | -------------------- | ----------------------------------- |
-| `before-init.ts` | `beforeInit` | Before the app initializes |
-| `after-init.ts` | `afterInit` | After the app initializes |
-| `before-registry-init.ts` | `beforeRegistryInit` | Before the ECS registry initializes |
-| `after-registry-init.ts` | `afterRegistryInit` | After the ECS registry initializes |
-| `before-run.ts` | `beforeRun` | Before the game loop starts |
-| `after-run.ts` | `afterRun` | After the game loop ends |
-
-## Examples
-
-**Generate a TypeScript client part:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-base --part=client
-```
-
-**Generate a server part with init hooks:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-base \
- --part=server \
- --initFunctions=true
-```
-
-**Generate a JavaScript client in a specific directory:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-base \
- --part=client \
- --language=js \
- --directory=./my-game
-```
diff --git a/docs/cli/schematics/2-schematics/4-part-main.mdx b/docs/cli/schematics/2-schematics/4-part-main.mdx
deleted file mode 100644
index 60a88dc..0000000
--- a/docs/cli/schematics/2-schematics/4-part-main.mdx
+++ /dev/null
@@ -1,77 +0,0 @@
----
-title: Part Main
-description: Generate the main entry point for a NanoForge client or server part
----
-
-import { Tooltip } from "mintlify/components";
-
-## Overview
-
-The `part-main` schematic reads the `.nanoforge/{part}.save.json` file produced by `part-base` and generates a fully wired `main.ts` (or `main.js`) entry point. It registers all libraries, components, systems, and entities declared in the save file.
-
-
- This schematic must be run after `part-base`.
-
-
-## Usage
-
-```bash
-schematics @nanoforge-dev/schematics:part-main --part=client
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| --------------- | ---------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `part` | `"client" \| "server"` | _(required)_ | The part of the application to generate |
-| `directory` | `string` | `.` | Project root directory |
-| `language` | `"ts" \| "js"` | `ts` | Language of the generated entry point |
-| `initFunctions` | `boolean` | `false` | Wire init lifecycle functions into the main file |
-| `saveFile` | `string` | — | Custom path to the save JSON file |
-| `outFile` | `string` | — | Custom output path for the generated main file |
-| `editor` | `boolean` | `false` | Generate the editor variant of the main file |
-
-## Output path resolution
-
-The generated file is placed at one of the following paths, in priority order:
-
-1. `outFile` — if provided explicitly
-2. `.nanoforge/editor/{part}/main.{language}` — if `editor: true`
-3. `{part}/main.{language}` — default
-
-## How it works
-
-`part-main` reads `{directory}/.nanoforge/{part}.save.json`, builds the full application bootstrap code, then writes the result as the entry point. Every time you add a component, system, or entity through the NanoForge CLI or editor, regenerating `part-main` keeps the entry point in sync with the save file.
-
-## Examples
-
-**Generate a client main file:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-main --part=client
-```
-
-**Generate a server main file with init hooks:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-main \
- --part=server \
- --initFunctions=true
-```
-
-**Generate with a custom save file and output path:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-main \
- --part=client \
- --saveFile=./custom.save.json \
- --outFile=./src/client/main.ts
-```
-
-**Regenerate the editor entry point:**
-
-```bash
-schematics @nanoforge-dev/schematics:part-main \
- --part=client \
- --editor=true
-```
diff --git a/docs/cli/schematics/2-schematics/4-system.mdx b/docs/cli/schematics/2-schematics/4-system.mdx
deleted file mode 100644
index 51ecf8d..0000000
--- a/docs/cli/schematics/2-schematics/4-system.mdx
+++ /dev/null
@@ -1,105 +0,0 @@
----
-title: System
-description: Generate a NanoForge ECS system
----
-
-import { Tooltip } from "mintlify/components";
-
-## Overview
-
-The `system` schematic scaffolds a new ECS system function for a NanoForge client or server part. The generated file includes the system function, a default export required for code generation, and an `EDITOR_SYSTEM_MANIFEST` required for the NanoForge editor to display and configure the system.
-
-## Usage
-
-```bash
-schematics @nanoforge-dev/schematics:system --part=client --name=movement
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| ----------- | ---------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `name` | `string` | `example` | System name |
-| `part` | `"client" \| "server"` | _(required)_ | The part of the application this system belongs to |
-| `directory` | `string` | `.` | Destination directory for the generated file |
-| `language` | `"ts" \| "js"` | `ts` | Language to use for the generated file |
-
-## Generated file
-
-`{directory}/{name}.system.ts`
-
-```ts
-import { type Context } from "@nanoforge-dev/common";
-import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-client";
-
-import { ExampleComponent } from "../components/example.component";
-
-export const movementSystem = (registry: Registry, ctx: Context) => {
- const entities = registry.getZipper([ExampleComponent]);
-
- entities.forEach((entity) => {
- if (entity.ExampleComponent.paramA === "end") {
- ctx.app.setIsRunning(false);
- return;
- }
-
- if (entity.ExampleComponent.paramB === 0) entity.ExampleComponent.paramA = "end";
-
- if (entity.ExampleComponent.paramB >= 0)
- entity.ExampleComponent.paramB = entity.ExampleComponent.paramB - 1;
- });
-};
-
-// Required to generate code
-export default movementSystem.name;
-
-// Required for the editor to display the system and generate code
-export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = {
- name: "movement",
- description:
- "This system end the game when paramB reaches 0 for any entity with ExampleComponent",
- dependencies: ["ExampleComponent"],
-};
-```
-
-## Editor manifest
-
-The `EDITOR_SYSTEM_MANIFEST` export is required for the NanoForge editor to discover the system and wire it into the game loop.
-
-| Field | Required | Description |
-| -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `name` | Yes | System name as displayed in the editor |
-| `description` | Yes | Human-readable description of what the system does |
-| `dependencies` | Yes | Component names this system depends on |
-
-## System signature
-
-Every NanoForge system follows the same function signature:
-
-```ts
-(registry: Registry, ctx: Context) => void
-```
-
-- **`registry`** — the ECS registry; use `registry.getZipper([...])` to query entities with specific components.
-- **`ctx`** — the application context; provides access to `ctx.app`, `ctx.assets`, and other engine services.
-
-## Examples
-
-**Generate a `PhysicsSystem` for the client:**
-
-```bash
-schematics @nanoforge-dev/schematics:system \
- --part=client \
- --name=physics \
- --directory=client/systems
-```
-
-**Generate a JavaScript server system:**
-
-```bash
-schematics @nanoforge-dev/schematics:system \
- --part=server \
- --name=sync-state \
- --language=js \
- --directory=server/systems
-```
diff --git a/docs/cli/schematics/2-schematics/5-docker.mdx b/docs/cli/schematics/2-schematics/5-docker.mdx
deleted file mode 100644
index ce32b7d..0000000
--- a/docs/cli/schematics/2-schematics/5-docker.mdx
+++ /dev/null
@@ -1,70 +0,0 @@
----
-title: Docker
-description: Generate a Dockerfile for a NanoForge application
----
-
-import { Tooltip } from "mintlify/components";
-
-## Overview
-
-The `docker` schematic generates a production-ready `Dockerfile` and a `.dockerignore` at the specified directory. The Dockerfile is tailored to the package manager you use — selecting the correct base image, lockfile, and install command automatically.
-
-## Usage
-
-```bash
-schematics @nanoforge-dev/schematics:docker
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| ---------------- | ------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `directory` | `string` | `.` | Destination directory for the generated files |
-| `packageManager` | `"npm" \| "yarn" \| "pnpm" \| "bun"` | `npm` | Package manager used by the application |
-
-## Generated files
-
-```
-{directory}/
-├── Dockerfile
-└── .dockerignore
-```
-
-## Dockerfile behaviour by package manager
-
-| Package manager | Base image | Install command |
-| --------------- | -------------- | -------------------------------------------------- |
-| `npm` | `node:25-slim` | `npm install --no-lockfile` |
-| `yarn` | `node:25-slim` | `yarn install --frozen-lockfile` |
-| `pnpm` | `node:25-slim` | `pnpm install --frozen-lockfile --allow-build=bun` |
-| `bun` | `oven/bun:1.3` | `bun install --frozen-lockfile` |
-
-The Dockerfile follows a standard multi-step approach:
-
-1. Copy `package.json` and the lockfile.
-2. Install dependencies with frozen lockfile for reproducible builds.
-3. Copy the rest of the source.
-4. Run `build`.
-5. Start with `start`.
-
-## Examples
-
-**Generate a Dockerfile for an npm project:**
-
-```bash
-schematics @nanoforge-dev/schematics:docker
-```
-
-**Generate a Dockerfile for a pnpm project:**
-
-```bash
-schematics @nanoforge-dev/schematics:docker --packageManager=pnpm
-```
-
-**Generate in a specific directory:**
-
-```bash
-schematics @nanoforge-dev/schematics:docker \
- --packageManager=bun \
- --directory=./my-game
-```
diff --git a/docs/cli/schematics/2-schematics/6-component.mdx b/docs/cli/schematics/2-schematics/6-component.mdx
deleted file mode 100644
index 9b14080..0000000
--- a/docs/cli/schematics/2-schematics/6-component.mdx
+++ /dev/null
@@ -1,120 +0,0 @@
----
-title: Component
-description: Generate a NanoForge ECS component
----
-
-import Tooltip from "mint/Tooltip";
-
-## Overview
-
-The `component` schematic scaffolds a new ECS component class for a NanoForge client or server part. The generated file includes the component class, a default export required for code generation, and an `EDITOR_COMPONENT_MANIFEST` required for the NanoForge editor to display and configure the component.
-
-## Usage
-
-```bash
-schematics @nanoforge-dev/schematics:component --part=client --name=health
-```
-
-## Options
-
-| Option | Type | Default | Description |
-| ----------- | ---------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `name` | `string` | `example` | Component name |
-| `part` | `"client" \| "server"` | _(required)_ | The part of the application this component belongs to |
-| `directory` | `string` | `.` | Destination directory for the generated file |
-| `language` | `"ts" \| "js"` | `ts` | Language to use for the generated file |
-
-## Generated file
-
-`{directory}/{name}.component.ts`
-
-```ts
-import { type EditorComponentManifest } from "@nanoforge-dev/ecs-client";
-
-export class HealthComponent {
- name = this.constructor.name;
-
- constructor(
- public paramA: string,
- public paramB: number,
- public paramC: boolean = false,
- ) {}
-
- get foo() {
- return "bar";
- }
-
- get paramAOrDefault() {
- return this.paramC ? this.paramA : "default";
- }
-
- addOne() {
- this.paramB += 1;
- }
-}
-
-// Required to generate code
-export default HealthComponent.name;
-
-// Required for the editor to display the component and generate code
-export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
- name: "Health",
- description: "Health component description",
- params: [
- {
- type: "string",
- name: "paramA",
- description: "Param A description",
- example: "Example value",
- },
- {
- type: "number",
- name: "paramB",
- description: "Param B description",
- example: 3,
- },
- {
- type: "boolean",
- name: "paramC",
- description: "Param C description",
- example: true,
- default: false,
- optional: true,
- },
- ],
-};
-```
-
-## Editor manifest
-
-The `EDITOR_COMPONENT_MANIFEST` export is required for the NanoForge editor to discover the component, render its configuration panel, and generate code. Each `params` entry describes one constructor parameter:
-
-| Field | Required | Description |
-| ------------- | -------- | ------------------------------------------------------------ |
-| `type` | Yes | Parameter type: `"string"`, `"number"`, or `"boolean"` |
-| `name` | Yes | Constructor parameter name |
-| `description` | Yes | Human-readable description shown in the editor |
-| `example` | Yes | Example value used in code generation |
-| `default` | No | Default value when the parameter is optional |
-| `optional` | No | When `true`, the editor treats the parameter as non-required |
-
-## Examples
-
-**Generate a `PlayerComponent` for the client:**
-
-```bash
-schematics @nanoforge-dev/schematics:component \
- --part=client \
- --name=player \
- --directory=client/components
-```
-
-**Generate a JavaScript server component:**
-
-```bash
-schematics @nanoforge-dev/schematics:component \
- --part=server \
- --name=network-player \
- --language=js \
- --directory=server/components
-```
diff --git a/docs/cli/schematics/2-schematics/3-component.mdx b/docs/cli/schematics/component.mdx
similarity index 99%
rename from docs/cli/schematics/2-schematics/3-component.mdx
rename to docs/cli/schematics/component.mdx
index 9b14080..9c2ec11 100644
--- a/docs/cli/schematics/2-schematics/3-component.mdx
+++ b/docs/cli/schematics/component.mdx
@@ -3,8 +3,6 @@ title: Component
description: Generate a NanoForge ECS component
---
-import Tooltip from "mint/Tooltip";
-
## Overview
The `component` schematic scaffolds a new ECS component class for a NanoForge client or server part. The generated file includes the component class, a default export required for code generation, and an `EDITOR_COMPONENT_MANIFEST` required for the NanoForge editor to display and configure the component.
diff --git a/docs/cli/schematics/1-overview.mdx b/docs/cli/schematics/overview.mdx
similarity index 85%
rename from docs/cli/schematics/1-overview.mdx
rename to docs/cli/schematics/overview.mdx
index 1b14655..58b5eb7 100644
--- a/docs/cli/schematics/1-overview.mdx
+++ b/docs/cli/schematics/overview.mdx
@@ -3,8 +3,6 @@ title: Schematics
description: Overview of the @nanoforge-dev/schematics package
---
-import { Card, CardGroup } from "mintlify/components";
-
## What are schematics?
NanoForge schematics are code generators built on [Angular DevKit](https://github.com/angular/angular-cli/tree/main/packages/angular_devkit/schematics). They produce the boilerplate files that every NanoForge project needs — from the initial application scaffold down to individual ECS components and systems.
@@ -33,18 +31,18 @@ schematics @nanoforge-dev/schematics: [options]
## Available schematics
-
+
Scaffold the root of a NanoForge monorepo: `nanoforge.config.ts`, `package.json`, TypeScript or
JavaScript config, and linting.
-
+
Generate a client or server project under `apps/` inside a workspace, including its
`main.ts` entry point, example component/system, and optional Dockerfile.
-
+
Scaffold an ECS component class with an editor manifest for use in the NanoForge editor.
-
+
Scaffold an ECS system function with an editor manifest for use in the NanoForge editor.
diff --git a/docs/cli/schematics/2-schematics/2-project.mdx b/docs/cli/schematics/project.mdx
similarity index 94%
rename from docs/cli/schematics/2-schematics/2-project.mdx
rename to docs/cli/schematics/project.mdx
index 1ba4517..d077f80 100644
--- a/docs/cli/schematics/2-schematics/2-project.mdx
+++ b/docs/cli/schematics/project.mdx
@@ -3,11 +3,9 @@ title: Project
description: Generate a NanoForge client or server project inside a workspace
---
-import { Tooltip } from "mintlify/components";
-
## Overview
-The `project` schematic generates a complete client or server project under `directory` (e.g. `apps/client`) inside a [`workspace`](./1-workspace): its own `package.json`, `nanoforge.config.ts`, `tsconfig.json`, example ECS component and system, `src/main.ts` entry point, and optionally a `Dockerfile` and lifecycle init functions. `directory` is the full destination path — it isn't appended with `part` automatically, so generating a client and a server side by side means passing e.g. `--directory=apps/client` and `--directory=apps/server` in two separate invocations.
+The `project` schematic generates a complete client or server project under `directory` (e.g. `apps/client`) inside a [`workspace`](/docs/cli/schematics/workspace): its own `package.json`, `nanoforge.config.ts`, `tsconfig.json`, example ECS component and system, `src/main.ts` entry point, and optionally a `Dockerfile` and lifecycle init functions. `directory` is the full destination path — it isn't appended with `part` automatically, so generating a client and a server side by side means passing e.g. `--directory=apps/client` and `--directory=apps/server` in two separate invocations.
For a standalone project (`workspace: false`), engine dependency versions are pinned to the newest release published at least 48h ago, mirroring pnpm's own `minimumReleaseAge` supply-chain protection. `@nanoforge-dev/ecs` and `@nanoforge-dev/network` are resolved directly under those same names — no aliasing to a different registry package. A standalone project also generates its own `allowBuilds` config (`pnpm-workspace.yaml`'s `allowBuilds` map, `package.json`'s `allowScripts` or `trustedDependencies`, depending on `packageManager`) since it has no parent workspace root to provide one — see `allowBuilds` below.
diff --git a/docs/cli/schematics/2-schematics/7-system.mdx b/docs/cli/schematics/system.mdx
similarity index 99%
rename from docs/cli/schematics/2-schematics/7-system.mdx
rename to docs/cli/schematics/system.mdx
index 51ecf8d..20f1409 100644
--- a/docs/cli/schematics/2-schematics/7-system.mdx
+++ b/docs/cli/schematics/system.mdx
@@ -3,8 +3,6 @@ title: System
description: Generate a NanoForge ECS system
---
-import { Tooltip } from "mintlify/components";
-
## Overview
The `system` schematic scaffolds a new ECS system function for a NanoForge client or server part. The generated file includes the system function, a default export required for code generation, and an `EDITOR_SYSTEM_MANIFEST` required for the NanoForge editor to display and configure the system.
diff --git a/docs/cli/schematics/2-schematics/1-workspace.mdx b/docs/cli/schematics/workspace.mdx
similarity index 97%
rename from docs/cli/schematics/2-schematics/1-workspace.mdx
rename to docs/cli/schematics/workspace.mdx
index 5f836f2..9b2571f 100644
--- a/docs/cli/schematics/2-schematics/1-workspace.mdx
+++ b/docs/cli/schematics/workspace.mdx
@@ -3,11 +3,9 @@ title: Workspace
description: Generate a NanoForge workspace (monorepo root)
---
-import { Tooltip } from "mintlify/components";
-
## Overview
-The `workspace` schematic creates the root of a NanoForge monorepo: the `nanoforge.config.ts` workspace declaration, `package.json`, and TypeScript or JavaScript base config. A workspace holds one or more projects generated with the [`project`](./2-project) schematic under `apps/`.
+The `workspace` schematic creates the root of a NanoForge monorepo: the `nanoforge.config.ts` workspace declaration, `package.json`, and TypeScript or JavaScript base config. A workspace holds one or more projects generated with the [`project`](/docs/cli/schematics/project) schematic under `apps/`.
`@nanoforge-dev/cli`, `@nanoforge-dev/config` (using the engine version resolved from `@nanoforge-dev/core`) and (for TypeScript) `typescript` are pinned to the newest registry version published at least 48h ago at generation time, mirroring pnpm's own `minimumReleaseAge` supply-chain protection so a freshly (and potentially compromised) published release isn't picked up immediately. Non-nanoforge packages like `typescript` are pinned to a specific version rather than a range; `typescript` is also kept on its `6.x` line rather than jumping to the `7.x` native rewrite.
diff --git a/docs/editor/editor/adapt-a-project.mdx b/docs/editor/editor/adapt-a-project.mdx
new file mode 100644
index 0000000..3476832
--- /dev/null
+++ b/docs/editor/editor/adapt-a-project.mdx
@@ -0,0 +1,37 @@
+---
+title: 'Bring an existing project'
+icon: 'wand-sparkles'
+description: 'What the editor changes so it can edit a game made without it, shown before it is done'
+---
+
+A game written before the editor, or by hand, works in it as it is. Some ways of writing it, though, keep parts of the game out of the panels. The **Project** screen counts them under **Adapt to the editor**, and **Show suggestions** lists them: one card each, saying what the editor can't do and why the change helps.
+
+Nothing changes on its own. A card's button shows the change first: every file it creates, changes or removes, with its lines. **Apply** makes it as one step: `Ctrl+Z` on the Project screen puts every file back. When the project is a Git repository, the preview reminds you to commit first, so you can compare afterwards. A file with unsaved changes is never overwritten: save it first.
+
+**Dismiss** puts a card away for this project. _Settings › Editor › Project › Dismissed suggestions_ brings it back.
+
+## What the report finds
+
+| Card | What the editor can't do | The change |
+| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| **Move … out of main.ts** | Components and systems defined in the app's entry file are not in the Components panel, have no documentation in the Inspector, and can't move to a shared library. | Each goes to a file of its own in the app's `components/` or `systems/` folder, with only the imports it uses. A helper only they use goes with them (an exported one stays: other files import it). `main.ts` imports them back. Refused when they use something `main.ts` keeps (a layer, a constant): they would import `main.ts` while it imports them, so move that to a module of its own first. |
+| **Split components.ts** | Several components (or systems) in one file can only be moved, renamed or removed together. | One file each. Every file that imported them imports each from its new file. |
+| **Share Position** | The client and the server each have their own copy: a change to one is not made to the other. | When the copies are the same (their imports and strings too), the component moves to a [shared library](/docs/editor/editor/components#share-between-client-and-server) both apps use (`libs/shared`, named after the project's scope, created if the project has none), and every import points at it. When they differ, or share a file with other items, the card says what to do first. |
+| **… imports main.ts** | A component or system that imports the app's entry file can't move to a shared library. | Nothing automatic: move what it uses from `main.ts` (a layer, a constant) to a module of its own. |
+| **Make main's entities a scene** | Entities `main` makes are there for the whole game. | They move into a scene, `Game`, loaded when the game starts. See [Scenes](/docs/editor/editor/scenes). `@nanoforge-dev/scene` goes in the app's `package.json` when another `package.json` of the project names it; otherwise the preview says to add it by hand. Refused when they use variables of `main` itself, or what `main.ts` exports (it would import the scene that imports it). |
+| **Register the editor library** | Without `@nanoforge-dev/editor-lib`, a game plays without the editor bridge: no Pause, Step or Stop, no World, Profiler or Network. | `app.use(new EditorLibrary())` in `main.ts`, and the dependency in `package.json`. |
+| **List … in libs** | An app imports a shared library its `nanoforge.config` does not list: the editor does not offer that library's items in the app. | The library is added to `libs` and to the app's `package.json`. |
+| **Install the dependencies**, **Install …** | Without `node_modules`, or without an engine library the app declares, the game can't build and the code editor knows nothing of the engine. | Runs the project's package manager. A library not published on npm yet (`@nanoforge-dev/scene`) is linked from an engine checkout. |
+
+
+ `@nanoforge-dev/scene` and the editor library with the bridge are not on npm yet. A project turned
+ into scenes installs them from an engine checkout until the engine publishes them.
+
+
+## Plugins the project needs
+
+When packages of the project suggest plugins, a notification names them with **Install for this project** (in `.nanoforge/plugins`) and **Install for me** (every project, and kept in your account's plugin list). Plugins load once the editor reloads. In a folder you have not trusted, the notification only names them: the project's packages choose those names, so trust the folder first.
+
+## Plugins can add checks
+
+A plugin adds its own cards with the `PROJECT_CHECKS` extension point: see [Extension points](/docs/editor/plugins/extension-points).
diff --git a/docs/editor/editor/code-editor.mdx b/docs/editor/editor/code-editor.mdx
new file mode 100644
index 0000000..7b596c4
--- /dev/null
+++ b/docs/editor/editor/code-editor.mdx
@@ -0,0 +1,58 @@
+---
+title: 'Code editor'
+icon: 'code'
+description: 'Edit the game code with types, errors and formatting'
+---
+
+The **Script** screen is a code editor with what an IDE has: completion, types of your code and of the engine, errors as you type, go to definition, rename, formatting.
+
+
+
+## Tabs and split
+
+Each open file is a tab. A tab follows its file when it is renamed or moved, and closes when the file is deleted (unless it has unsaved changes). `Ctrl+\` splits the editor in two groups side by side, each with its own tabs. `Alt+W` or a middle click closes a tab.
+
+## Saving
+
+- `Ctrl+S` saves the file, and `Ctrl+K` then `S` saves them all; a dot on the tab marks unsaved changes.
+- Unsaved changes survive a reload of the page: they are kept until you save or revert.
+- **Play saves every open file first** (the _Save all before Play_ setting).
+
+_Settings › Editor › Code editor_ has the automatic options, under _Saving_ and _Actions on save_:
+
+| Setting | Does |
+| -------------------------------- | ---------------------------------------------------------------- |
+| Save after a delay | Saves when you stopped typing for a moment. |
+| Save when the editor loses focus | Saves when you leave the editor, switch tab or leave the window. |
+| Reformat with Prettier on save | Reformats at each save. |
+| Organize imports on save | Sorts and cleans the imports of TypeScript and JavaScript files. |
+
+## Find your way in the code
+
+| To | Press |
+| -------------------------- | ---------------------- |
+| Go to definition | `F12`, or `Ctrl`+click |
+| Open a file by name | `Ctrl+P` |
+| Go to a line | `Ctrl+G` |
+| Go to a symbol of the file | `Ctrl+Shift+O` |
+| Rename a symbol everywhere | `F2` |
+| Format the file | `Shift+Alt+F` |
+| Organize imports | `Shift+Alt+O` |
+
+Definitions inside engine packages (`@nanoforge-dev/*`) and installed packages open read-only.
+
+## Errors
+
+TypeScript errors are underlined in the code and listed in the **Problems** panel, for every file of the project, open or not. A failed build adds its errors there too. In the panel, the arrow keys go through files and problems (Left and Right fold a file), and `Enter` opens one.
+
+## Formatting
+
+Formatting uses **the project's own Prettier**, with its configuration and plugins. A hosted editor uses a built-in Prettier with the project's `.prettierrc`.
+
+## When a file changes on disk
+
+A file without unsaved changes reloads silently. A file **with** unsaved changes shows a banner: **Compare** (your version next to the one on disk), **Keep mine**, or **Load disk version**.
+
+## Panels beside the code
+
+When the open file defines a component, a **Component** panel can show next to the code (a toggle in the editor's toolbar): see [Components](/docs/editor/editor/components#how-a-component-looks-in-the-inspector).
diff --git a/docs/editor/editor/components.mdx b/docs/editor/editor/components.mdx
new file mode 100644
index 0000000..21170b8
--- /dev/null
+++ b/docs/editor/editor/components.mdx
@@ -0,0 +1,105 @@
+---
+title: 'Components'
+icon: 'blocks'
+description: 'Create components, use them, and choose how they look in the inspector'
+---
+
+A component is the data of an entity: a position, a speed, a sprite. It holds no logic; [systems](/docs/editor/editor/systems) use it.
+
+A component is a class:
+
+```ts
+/**
+ * Where an entity is, in viewport pixels.
+ * @component
+ */
+export class Position {
+ name = 'Position';
+ constructor(
+ public x = 0,
+ public y = 0,
+ ) {}
+}
+```
+
+## The Components panel
+
+
+
+The panel lists the components (**C**) and systems (**S**) the selected app can use, grouped by where they come from:
+
+- **App**: the app's own;
+- **Shared library**: code shared by the client and the server;
+- **Installed packages**: read-only, with a lock.
+
+Select one to read its description, its parameters and where it is defined. The search box filters by name.
+
+An item marked _untagged_ was recognized from the code but has no `@component` or `@system` tag: add the tag to make it explicit.
+
+## Create a component
+
+**New › New component in app**, then a name. The file is created in the app's components folder, with its tags, and opens in the code editor.
+
+## Add it to an entity
+
+Select an entity in the **Hierarchy**, select the component in the panel and click **Add to** the entity; or use **Add component…** in the Inspector. The component and its import are added to `main.ts`.
+
+## Share between client and server
+
+A **shared library** holds components and systems that both apps use.
+
+- **New › New shared library…** creates it (a folder in `libs/` and a package name such as `@my-game/shared`).
+- **New › New component in shared library** creates a component there.
+- **Move to shared library** moves an app's component into it and rewrites every import in the project, in one step you can undo.
+
+Apps import shared code by package name: `@my-game/shared/components/player`.
+
+A new library is used by every app. The [Project screen](/docs/editor/editor/overview#the-project-screen) lists the libraries and chooses which apps use each one: an app is only offered the components and systems of the libraries it uses.
+
+## Components from packages
+
+Packages installed from [File › Packages…](/docs/editor/editor/plugins-and-packages) bring components you can use as they are. To change one, use **Copy to…**: it copies the component into your app or a shared library.
+
+## How a component looks in the inspector
+
+The author of a component chooses how its parameters show, with tags in the documentation comments. Nothing changes in the game.
+
+```ts
+/**
+ * Where an entity is, in viewport pixels.
+ *
+ * @component
+ * @group Coords color=#4aa3ff - Position from the top-left corner.
+ */
+export class Position {
+ name = 'Position';
+ constructor(
+ /** Distance from the left edge. @group Coords @preset vector.x */
+ public x = 0,
+ /** Distance from the top edge. @group Coords @preset vector.y */
+ public y = 0,
+ /** Draw order. @label Layer @color orange */
+ public z = 0,
+ /** Draws the path the entity followed. @hidden */
+ public trail = false,
+ ) {}
+}
+```
+
+| Tag | Effect |
+| ------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
+| `@group Name` | Puts the parameter in a foldable group. Declare the group in the class comment to give it a color and a description. |
+| `@preset vector.x` / `vector.y` | Shows several parameters as one control. Presets: `vector`, `size`, `color`, and those of plugins. |
+| `@label Text` | The name shown instead of the parameter's. |
+| `@color orange` | Colors the name. |
+| `@hidden` | Hidden by default; _Show hidden_ in the inspector reveals it. |
+| `@asset .png .jpg` | A text parameter that names an asset: the inspector offers the app's assets of these types (`/textures/hero.png`). |
+| The comment's text | Shown behind the ⓘ next to the name. |
+
+### Without writing tags
+
+Open the component's file: the **Component** panel beside the code (a toggle in the editor's toolbar, or _Edit layout_ in the inspector's ⋯ menu and in the Components panel) has a control for each of these, and a preview. It writes the tags for you. A tag that can't apply (a preset missing a slot) is a warning on the component, in the panel, in the code and in **Problems**.
+
+## Two components with the same name
+
+The engine finds a component by its `name`. When an app can use two components with the same name (yours and a package's), the panel warns, and the app's own is the one used.
diff --git a/docs/editor/editor/entities.mdx b/docs/editor/editor/entities.mdx
new file mode 100644
index 0000000..b970f49
--- /dev/null
+++ b/docs/editor/editor/entities.mdx
@@ -0,0 +1,62 @@
+---
+title: 'Entities'
+icon: 'box'
+description: 'The entities of an app: hierarchy, inspector and the Scene screen'
+---
+
+Entities are the objects of your game: the player, the ball, the background. An entity is only a name; **components** give it data, and **systems** make it act.
+
+In NanoForge, entities are created in the app's `main.ts`: In a game made of [scenes](/docs/editor/editor/scenes), each scene creates its own in its `setup`, edited the same way.
+
+```ts
+const ball = registry.spawnEntity();
+registry.addComponent(ball, new Position(960, 540));
+```
+
+The editor reads that file and shows it as a hierarchy. When you change something in the panels, it edits those lines. When you edit the lines by hand, the panels follow.
+
+
+
+## Choose the app
+
+A multiplayer game has a client and a server, each with its own entities. The selector at the top of the **Hierarchy** panel chooses which one you edit.
+
+## The hierarchy
+
+Entities are listed under the name of their variable (`ball`, `paddle1`), with their components beside it.
+
+| To | Do |
+| ----------------- | --------------------------------------------------------------------------- |
+| Add an entity | **Add entity** (the **+** button). Give it a name: it becomes the variable. |
+| Rename | `F2`, or right-click › Rename. The variable is renamed. |
+| Duplicate, remove | Right-click |
+| Reorder | Drag an entity up or down, or `Alt+Up` / `Alt+Down` (right-click › Move up) |
+| Find | The filter box matches names and components |
+
+Every change is one step of the file's history: `Ctrl+Z` undoes it.
+
+### Entities "from code"
+
+Entities created in a way the editor cannot model (in a loop, in a helper function, under a condition) are listed greyed, with a lock. They cannot be changed from the panels; _Open in code_ jumps to their lines. The editor never rewrites code it does not understand.
+
+## The inspector
+
+Select an entity: the **Inspector** shows its components, with one field per parameter.
+
+- Change a value: only that value changes in the code.
+- **Add component…** lists the components the app can use. The import is added for you.
+- The **⋯** menu of a component removes it, opens its code, or edits how it is laid out.
+
+Fields follow the parameter's type: numbers, text, lists of choices, switches, colors. A value the editor has no field for (an engine object such as `new Rect(…)`) is shown as code, which you can edit.
+
+## The Scene screen
+
+The **Scene** screen draws the entities of the app in 2D: each one at its position, with its rectangle or circle.
+
+- **Click** a shape to select the entity.
+- **Drag** it to move it: its position is written to `main.ts`. With the scene focused, the **arrow keys** move the selected entity by 1 unit (10 with `Shift`).
+- Scroll to zoom, drag the background to pan; **Fit** shows everything.
+
+## While the game plays
+
+The hierarchy and the inspector switch to the **running game**: values move as the game runs, and entities created at runtime are listed too. See [Play the game](/docs/editor/editor/play#edit-the-running-game).
diff --git a/docs/editor/editor/files.mdx b/docs/editor/editor/files.mdx
new file mode 100644
index 0000000..a634f6c
--- /dev/null
+++ b/docs/editor/editor/files.mdx
@@ -0,0 +1,46 @@
+---
+title: 'Files'
+icon: 'folder-tree'
+description: 'Browse and organize the project files'
+---
+
+The **Files** panel shows the project's folders as a tree and, below it, the selected folder as a grid with thumbnails of images. The buttons at the top switch between the tree alone and the tree with the grid. In the grid, the arrow keys move between files, `Enter` opens one, `Space` selects it (`Ctrl+Space` adds it to the selection) and `Backspace` goes to the parent folder.
+
+## Open
+
+Double-click a file, or select it and press `Enter`. Code and text files open in the [code editor](/docs/editor/editor/code-editor). Images, sounds and videos open in a preview. _Open with_ in the right-click menu lists other editors when plugins provide some.
+
+## Create
+
+The **+** button, or right-click a folder and **New**: a file, a folder, or a template. Plugins add templates: the ECS plugin adds _Component_ and _System_ in the folders of an app or a shared library, which create the file with its documentation tags (`@side` from the app).
+
+## Organize
+
+| To | Do |
+| ------------ | --------------------------------------------------------------------------------------------- |
+| Rename | `F2`, or right-click › Rename |
+| Move | Drag the file onto a folder, or cut and paste |
+| Copy | `Ctrl+C` then `Ctrl+V`; `Ctrl+D` duplicates in place |
+| Delete | `Delete`. A folder or several files ask first. |
+| Import | Drop files from your computer onto a folder, or the import button |
+| Download | Right-click › Download. A folder downloads as a `.zip` (without `nf_modules`, 1 GiB at most). |
+| Show on disk | Right-click › Reveal in file manager (local editors) |
+
+Every one of these can be undone with `Ctrl+Z` while the Files panel has focus. A deleted file goes to the editor's trash and comes back on undo; the trash is emptied of what was deleted over 30 days ago.
+
+## Search
+
+The box at the top filters by name. Letters only need to be in order, and the matches stay in their folders.
+
+## Hidden files
+
+- The panel hides `node_modules`, `dist`, and files starting with a dot (except `.env`). The eye button shows them; _Settings › Editor › Files_ changes the list.
+- A `.nfignore` file at the project root (same syntax as `.gitignore`) hides files from the **whole editor**: this panel, the file pickers and the code analysis. Builds and the game still see them.
+
+## Packages
+
+When the project has installed packages, they show in a separate **Packages** section with a lock: they are read-only. To change a component of a package, copy it into your app from the [Components](/docs/editor/editor/components) panel. Packages are installed from [File › Packages…](/docs/editor/editor/plugins-and-packages).
+
+## Marks
+
+In a Git repository, changed files carry a mark after their name and a color: modified, added, untracked. See [Git](/docs/editor/editor/git).
diff --git a/docs/editor/editor/git.mdx b/docs/editor/editor/git.mdx
new file mode 100644
index 0000000..d18136c
--- /dev/null
+++ b/docs/editor/editor/git.mdx
@@ -0,0 +1,66 @@
+---
+title: 'Git'
+icon: 'git-branch'
+description: 'Commit, push, branches and history, from the editor'
+---
+
+In a local editor, the **VCS** menu and two panels work with the project's Git repository, using the `git` installed on your machine and the credentials it already has.
+
+A project that is not a repository yet: _VCS › Initialize repository_.
+
+## Commit
+
+The **Commit** panel on the left lists what changed since the last commit, as files with their folder beside the name:
+
+- **Changes**: files Git knows that you modified, added or deleted;
+- **Unversioned files**: files Git does not know yet.
+
+1. **Check** the files to commit. A group's checkbox checks all its files.
+2. Write a message.
+3. **Commit**, or **Commit and push…**
+
+**Amend** replaces the last commit instead of adding one.
+
+| To | Do |
+| -------------------------- | ------------------------------------------------------------------- |
+| See what changed in a file | Double-click it: the diff opens in the code editor. |
+| Undo your changes to files | Select them, then **Rollback**. It asks first: it cannot be undone. |
+| Start tracking a new file | Right-click › Add to VCS |
+| Ignore a file | Right-click › Add to .gitignore |
+| Copy a file's path | Right-click › Copy path |
+| Put changes aside | The **Stash** tab: Stash changes, then Apply, Pop or Drop |
+
+Checking a file only chooses what is committed. Selecting rows (click, `Ctrl`+click, `Shift`+click, or a click on a group to select all its files) is what Rollback and the other actions act on.
+
+From the keyboard, the arrow keys go through groups and files: `Left` folds a group, `Right` unfolds it, `Space` checks the selected files (or a group's files), `Enter` shows a file's diff, and the menu key opens the right-click menu.
+
+## Update and push
+
+- _VCS › Update project_ pulls the changes of the remote branch.
+- _VCS › Push…_ shows the commits that would be sent, then pushes them.
+- _VCS › Fetch_ reads the remote without changing your files.
+
+The status bar shows the branch and what is ahead and behind (`main ↑1 ↓2`).
+
+## Branches and history
+
+The **Git** panel at the bottom has three parts:
+
+- **Branches**: the current one, local ones, and remote ones. Double-click a branch to check it out. Right-click for _New branch from…_, _Update_, _Push…_, _Delete_.
+- **Commits** of the selected branch, with a filter by text, author and date.
+- **Changed files** of the selected commit, and its details: the whole message, hash, author, date. Double-click a file to compare. The panel keeps the selected branch and commit.
+
+_VCS › New branch…_ creates a branch from the current commit and switches to it.
+
+## Marks in the Files panel
+
+Changed files are colored and carry a mark in the **Files** panel, and folders that hold changes carry a dot.
+
+## Conflicts
+
+After an update that conflicts, the files show under **Merge conflicts**. Open one, fix it in the code editor, then **Mark resolved**.
+
+
+ Git works on the project's own repository only, and in local editors. Hosted projects are saved to
+ their repository by the platform.
+
diff --git a/docs/editor/editor/layout.mdx b/docs/editor/editor/layout.mdx
new file mode 100644
index 0000000..68c70d4
--- /dev/null
+++ b/docs/editor/editor/layout.mdx
@@ -0,0 +1,54 @@
+---
+title: 'Layout'
+icon: 'layout-panel-left'
+description: 'Move, float and close panels, and save layouts'
+---
+
+The editor has six **docks**, as in IntelliJ: left top, left bottom, right top, right bottom, bottom left and bottom right. Their panels are icons in the **stripes** on the edges of the window (hover one for its name):
+
+- the left stripe holds the left top dock, then, under a line, the left bottom dock, and at its foot the bottom left dock;
+- the right stripe holds the right docks the same way, and the bottom right dock at its foot.
+
+The layout is saved with the project and restored when you come back.
+
+## Show and hide panels
+
+- **Click an icon** to show its panel in its dock. Click it again to hide the dock.
+- The panel's header has its title, a **⋮** menu and **Hide** (**−**).
+- _View › Docks_ shows or hides a whole dock, and _View › Panels_ shows a panel that was closed.
+
+## Move a panel
+
+- **Drag its icon** to another group of a stripe, or between the icons of a group to reorder them. You can also drag a panel by its header, onto a stripe or a dock. Zones light up to show where it will land.
+- Drag it **out of the docks** to make a **floating** window. Drag it by its title, resize it by its edges, and drag its tab back to a dock to dock it again.
+- **Right-click an icon** (or the header) for _Hide_, _Close_, _Close others_, _Float_ and _Move to_ (a dock).
+
+## Resize
+
+- Drag the line between two docks, or between a dock and the screen.
+- Or press `Tab` until the line is focused, then use the arrow keys (`Shift` for bigger steps): the change is one undo step.
+
+## Focus with the keyboard
+
+`F6` moves the focus to the next part of the editor (a dock, the screen), and `Shift+F6` to the previous one.
+
+In a row of tabs or panel icons, the arrow keys move between them, `Enter` shows one and `Delete` closes it.
+
+## Layouts
+
+_View › Layouts_:
+
+- **Save layout** keeps the current arrangement under a name;
+- the saved layouts are listed there: choose one to switch to it;
+- **Simple layout** shows the main panels only (Files, Hierarchy, Scenes, Inspector, Console), **All panels** every one; each puts the layout back to that default, and becomes the default of _Reset layout_ (the setting _Default layout_). A new editor starts with the simple one.
+- **Reset layout** goes back to the default.
+
+Moving, closing, floating and resizing a panel are steps you can undo: `Ctrl+Z` with the focus on the layout, or in the **History** panel under _Layout_.
+
+## While playing
+
+With _Settings › Editor › Game view › Maximize on play_, the docks and stripes hide while the game plays and come back when it stops.
+
+## Theme
+
+The editor follows the light or dark mode of your system until you choose a theme (_Match the system_ in _Settings › Appearance_). _View › Toggle light/dark theme_, or _Settings › Appearance_ to choose one. Plugins can add themes.
diff --git a/docs/editor/editor/overview.mdx b/docs/editor/editor/overview.mdx
new file mode 100644
index 0000000..8531ddb
--- /dev/null
+++ b/docs/editor/editor/overview.mdx
@@ -0,0 +1,85 @@
+---
+title: 'Find your way around'
+icon: 'compass'
+description: 'Screens, panels, menus and the command palette'
+---
+
+
+
+## Screens
+
+The center of the editor shows one **screen** at a time, chosen in the top bar.
+
+| Screen | Shows |
+| ----------- | --------------------------------------------------------------------------------------- |
+| **Project** | The project's apps and shared libraries. See [The Project screen](#the-project-screen). |
+| **Scene** | The entities of an app, drawn in 2D. Select and drag them. See [Entities](/docs/editor/editor/entities). |
+| **Script** | The code editor. See [Code editor](/docs/editor/editor/code-editor). |
+| **Game** | The running game. See [Play the game](/docs/editor/editor/play). |
+
+## The Project screen
+
+The Project screen lists what the project is made of, and changes it.
+
+- **Adapt to the editor**: what the editor can't edit well in this project, with a change to preview and apply (see [Bring an existing project](/docs/editor/editor/adapt-a-project)).
+- **Apps**: each client and server, with its folder, its engine libraries and the shared libraries it uses. **Add app** creates a client or a server, empty or as a copy of another one. An empty app needs its dependencies: the editor offers to install them.
+- **Shared libraries**: code that several apps use (see [Components](/docs/editor/editor/components#share-between-client-and-server)). **Add shared library** creates one. Under **Used by**, tick the apps that use it: the editor writes it in the `libs` of each app's `nanoforge.config.ts` (`libs: ["../../libs/shared"]`) and in its `package.json`. Edit `libs` by hand and the screen follows.
+- The **⋯** menu of a card renames or removes it. Renaming a library rewrites every import of it. A library that code still imports can't be removed: the editor names the files.
+
+Each change is one step you can undo with `Ctrl+Z` while the Project screen has the focus.
+
+## Panels
+
+Around the screen, **panels** sit in five docks: two on the left, two on the right, one at the bottom.
+
+| Panel | For |
+| ------------------------ | ---------------------------------------------------------------------------------------- |
+| Files | The project's files and folders. See [Files](/docs/editor/editor/files). |
+| Hierarchy, Inspector | Entities and their components. See [Entities](/docs/editor/editor/entities). |
+| Components, Systems | What the app can use and what it runs. See [Components](/docs/editor/editor/components), [Systems](/docs/editor/editor/systems). |
+| Commit, Git | Changes, commits and branches. See [Git](/docs/editor/editor/git). |
+| History | Every change you can undo. |
+| Console, Problems | Output of the game and the editor; errors in the code. |
+| Profiler, Network, World | The running game, in detail. See [Play the game](/docs/editor/editor/play#inspect-the-running-game). |
+
+_View › Panels_ lists every panel, and shows one that was closed.
+
+The first time a panel shows, a tip above it says what it is for, with a link to its page here. _Got it_ puts it away for good; to see a tip again, remove its panel from **Dismissed tips** in _Settings › Editor › Appearance_.
+
+## Menus
+
+- **File**: Packages…, Settings…, Close project.
+- **Edit**: undo and redo.
+- **View**: the command palette, panels, screens, docks, layouts, light or dark theme.
+- **Run**: Play, Pause, Step, Restart, Stop, and the play modes.
+- **VCS**: Git commands.
+- **Help**: documentation.
+
+Plugins add their own entries.
+
+## The command palette
+
+Press `Ctrl+Shift+P` and type what you want to do. Every action of the editor is there, with its shortcut.
+
+
+
+The same box finds other things, depending on how the text starts:
+
+| Type | To | Shortcut |
+| ---------------- | ------------------------------- | -------------- |
+| `>` and a name | run a command | `Ctrl+Shift+P` |
+| a name | open a file of the project | `Ctrl+P` |
+| `:12` or `:12:4` | go to a line of the open file | `Ctrl+G` |
+| `@` and a name | go to a symbol of the open file | `Ctrl+Shift+O` |
+
+Letters only need to be in order, not next to each other. The commands you ran last are listed first.
+
+## Undo
+
+`Ctrl+Z` undoes the last change **of what has focus**: the file you edit, the Files panel, the layout. Each has its own history, so undoing a file move does not undo your code.
+
+The **History** panel (_View › Panels › History_) lists the steps of what you are working on. Click a step to go back to it; the _All_ switch shows every history.
+
+## Problems and the status bar
+
+The status bar shows the count of errors and warnings in the project's code; click it to open **Problems**, where each one opens its file at the right line.
diff --git a/docs/editor/editor/play.mdx b/docs/editor/editor/play.mdx
new file mode 100644
index 0000000..418b6ff
--- /dev/null
+++ b/docs/editor/editor/play.mdx
@@ -0,0 +1,104 @@
+---
+title: 'Play the game'
+icon: 'play'
+description: 'Run the game in the editor, watch it, and change it while it runs'
+---
+
+Press **Play** in the top bar, or `F5`. The editor saves your files, builds the game, and runs it in the **Game** screen.
+
+
+
+| Action | Shortcut |
+| ------------------ | -------------------------------- |
+| Play | `F5` |
+| Pause, then resume | the Pause button, `F5` to resume |
+| Step one frame | the Step button, while paused |
+| Restart | `Ctrl+Shift+F5` |
+| Stop | `Shift+F5` |
+
+The game gets the keyboard when it starts. Press `Escape` to give it back to the editor. Stopping returns to the screen you were on.
+
+
+ The game runs in a **local** editor (`nf editor`). A hosted editor does not build or run project
+ code yet.
+
+
+## Play modes
+
+A multiplayer game has a client and a server. The **Run** menu chooses what plays:
+
+| Mode | Runs |
+| -------------------- | ---------------------------------------------------------------------- |
+| **Play** | The server and a client (or the client alone when there is no server). |
+| **Play client only** | The client, for a game whose server runs elsewhere. |
+| **Play server only** | The server, without a game view. |
+
+_Settings › Runtime › Play mode_ sets what `F5` does. While the game plays, the Run menu can open **another client** in a new window, to test two players.
+
+A project can have several clients or several servers. Play starts one of each: the Run menu then shows **Client app** or **Server app**, to choose which one. The choice is kept with the project, on your machine.
+
+## The Game screen
+
+The toolbar above the game:
+
+| Tool | Does |
+| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
+| **Resolution** | _Fit_ fills the screen. Or a fixed size: 1920×1080, 1280×720, 1024×768, a phone, a tablet (with portrait or landscape), or a custom size. |
+| **Zoom** | For fixed sizes. _Pixel perfect_ keeps whole zoom steps and sharp pixels. |
+| **Stats** | An overlay: ticks per second, tick time, the slowest libraries, memory. |
+| **Mute** | Mutes the game's sounds and music. |
+| **Screenshot** | Saves the game as a PNG in the project's `screenshots/` folder and copies it. |
+| **Pop out** | Moves the running game to its own browser window. Closing it brings the game back. |
+
+While paused, the game is dimmed with a _Paused_ badge. The status bar shows the speed of the client and the server.
+
+## The console
+
+The **Console** shows what the game prints, the output of builds, and messages of the editor and its plugins.
+
+- **Chips** at the top show or hide groups: Game, Build, Tasks, Editor, Plugins. A dot on a hidden group means it holds warnings or errors.
+- **Levels**: debug, info, warnings, errors. **Search** filters by text.
+- A logged **object** shows as one line that expands into a tree.
+- A **file path** in a line is a link: it opens the file at that line. Lines of the game show where they were logged (`main.ts:12`).
+- Identical lines in a row are grouped with a count.
+- The Console follows new lines, except while the pointer is over them. `Ctrl`+`Alt`+`E` shows only errors, and every level again.
+- **Save shown lines** (the download button, or right-click) saves what the filters show as a `.log` file.
+
+## Edit the running game
+
+While the game plays, the **Hierarchy** and the **Inspector** show the live world of the client or the server (the selector at the top of the Hierarchy chooses which).
+
+- Change a value in the Inspector: the **running game** changes at once. The code does not.
+- Add or remove a component, spawn or remove an entity: same.
+- In the **Scene** screen, drag a shape to move the entity in the running game.
+- In the **Game** screen, turn on **Move entities** in its toolbar: the entities are outlined over the game, and you drag them there the same way. While it is on, the pointer goes to the editor, not to the game. In a networked game the server sends the positions of what it owns: pause the game before moving those, then apply.
+- **Apply to code** writes the changes of an entity to `main.ts`; **Apply all changes to code**, in the Hierarchy's toolbar, writes those of every entity. Entities spawned at runtime exist only in the game and cannot be applied.
+- In the **Systems** panel, switch a system off to see the game without it.
+
+Stopping the game drops the changes that were not applied; the editor offers to apply them first. The ECS setting _Apply live edits to code_ writes every live change to code as it happens.
+
+## Inspect the running game
+
+Three panels at the bottom, each with a Client / Server selector.
+
+
+
+- **Profiler**: tick time over the last two minutes, against a budget line (16.7 ms by default); spikes are marked. Below, the time per engine library and **per system**. Click the chart to freeze it on a moment. **Pause**, **Clear** and **Export** (CSV or JSON) are in its toolbar.
+- **Network**: the packets sent and received, with their size, type name and decoded content; filters by direction, transport and text; charts of bytes and packets per second. **Pause** keeps the list still, **Clear** starts it over, **Export** saves the packets shown (CSV or JSON).
+- **World**: every entity of the running game with its components, read-only, with a search: `Position` (has the component), `Position.x > 100`, `#12` (an entity id).
+
+They ask the game for data only while they are shown.
+
+## When something fails
+
+- A **build error** stops Play: the error is in the Console and in **Problems**, with its file and line.
+- A game that **crashes** shows its error in the Console; links in the stack open your source files.
+- A game that does not register the **editor library** still plays, without pause, stats, live editing and the inspectors; the editor says so. Click **Add the editor library** in its message, or add it yourself to the app's `main.ts`, then play again:
+
+ ```ts
+ import { EditorLibrary } from '@nanoforge-dev/editor-lib';
+
+ app.use(new EditorLibrary());
+ ```
+
+ It does nothing when the game is not started by the editor. It needs NanoForge engine 2.0 or later: with an older engine, update the engine packages.
diff --git a/docs/editor/editor/plugins-and-packages.mdx b/docs/editor/editor/plugins-and-packages.mdx
new file mode 100644
index 0000000..9574007
--- /dev/null
+++ b/docs/editor/editor/plugins-and-packages.mdx
@@ -0,0 +1,68 @@
+---
+title: 'Plugins and packages'
+icon: 'plug'
+description: 'Add tools to the editor and ready-made components to your game'
+---
+
+Two different things can be installed:
+
+- a **plugin** adds something to the **editor**: a panel, a tool, a command;
+- a **package** adds something to your **game**: components, systems, assets.
+
+Installing is for local editors.
+
+## Plugins
+
+_File › Settings… › Plugins_.
+
+
+
+### Marketplace
+
+Search, select a plugin to read about it, then **Install**:
+
+- **For me**: in every project you open on this machine;
+- **For this project**: in the project's `.nanoforge/plugins` folder, which can be committed so the whole team has it. On a hosted editor, a project's own plugins load only after you choose **Allow its plugins** for that project: anyone who can change the project can change them.
+
+A plugin starts working after a reload of the editor: the page offers **Reload now**. When a newer version exists, **Update** shows instead of _Installed_.
+
+### Installed
+
+Every plugin of the editor, with its version and where it comes from. The switch turns a plugin off (after a reload). Plugins installed from the marketplace can be **updated** and **uninstalled** here; built-in ones cannot.
+
+### Plugins a project suggests
+
+A package can suggest plugins that make it easier to use. When a project opens with such packages and the plugins are missing, the editor says which.
+
+## Packages
+
+_File › Packages…_
+
+
+
+### Browse
+
+Search, select a package to see what it depends on, then **Install**. The package and the packages it needs go to the project's `nf_modules` folder, and their components and systems show in the [Components](/docs/editor/editor/components) panel at once.
+
+### Installed
+
+The project's packages, with their version. **Update** moves one to a newer version; **Uninstall** removes it, with the packages only it needed. A package that another one needs cannot be removed first.
+
+### What is written in the project
+
+| File | Holds |
+| ------------------------------ | -------------------------------------------------------------------------------- |
+| `nanoforge.packages.json` | The packages the project asks for. Commit it. |
+| `nanoforge.packages.lock.json` | The exact versions installed. Commit it. |
+| `nf_modules/` | The packages themselves. Read-only in the editor. |
+| `tsconfig.json` | Import paths, so code imports a package by name: `@acme/shapes/components/hull`. |
+
+`nf_modules` can be left out of Git: on a fresh clone, the Packages dialog sees what is missing and offers **Restore packages**.
+
+### Changing a package's component
+
+Packages are read-only. In the Components panel, **Copy to…** copies a component into your app, where it is yours to edit.
+
+## Writing your own
+
+See [Plugins](/docs/editor/plugins/overview).
diff --git a/docs/editor/editor/scenes.mdx b/docs/editor/editor/scenes.mdx
new file mode 100644
index 0000000..7234ba0
--- /dev/null
+++ b/docs/editor/editor/scenes.mdx
@@ -0,0 +1,87 @@
+---
+title: 'Scenes'
+icon: 'layers'
+description: 'Split a game into scenes: the scene tree, their entities and systems, and the scene vars'
+---
+
+A game with scenes uses the engine's scene module (`@nanoforge-dev/scene`): a menu, levels, a pause screen… Each scene makes its own entities and systems when it is loaded, and they go away when it is unloaded. The editor's **Scenes** and **Vars** panels show up for any app that depends on `@nanoforge-dev/scene`.
+
+A scene is a class extending `EcsScene` (from `@nanoforge-dev/ecs/scene`). Its `setup` is written like an app's `main.ts`:
+
+```ts
+/**
+ * First level: the bricks.
+ * @scene
+ * @side client
+ * @vars bricksLeft
+ */
+export class Level1 extends EcsScene {
+ static override parent = Run;
+
+ override setup(registry: Registry, ctx: Context) {
+ const wall = registry.spawnEntity();
+ registry.addComponent(wall, new Position(40, 90));
+ registry.addSystem(levelFlow);
+ }
+}
+```
+
+The app's `main.ts` gives `SceneLibrary` the scene to start with, and every scene by id:
+
+```ts
+app.use(new SceneLibrary({ initial: Menu, scenes: { Menu, Run, Level1, Pause } }));
+```
+
+## The scene tree
+
+The **Scenes** panel lists the app's scenes as a tree: a scene sits under its parent (`static parent`). Loading a scene loads its parents first; the initial scene has a flag.
+
+Its first row is **main.ts**, the app itself: what `main` creates is in the game whatever scene is loaded.
+
+| To | Do |
+| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
+| Create a scene | **New scene** (the + button), or _New scene under …_ on a scene. A file is created in the app's scenes folder and opens in the code editor. |
+| Rename | `F2`, or _Rename_. Every use of the class follows, and its file when it is named after it. |
+| Change its parent | Drag it onto another scene, next to one, or _Move to the root_. |
+| Start the game on it | _Set as initial scene_. |
+| Delete | _Delete_. Its children lose their parent. Code that still uses the class must be changed. |
+
+Each of these is one step you can undo (`Ctrl+Z` in the panel).
+
+## Edit a scene
+
+Select a scene in the Scenes panel: the **Hierarchy**, the **Inspector**, the **Systems** panel and the **Scene** screen now edit that scene's `setup`. Select **main.ts** (the default) to edit the app's `main`. Everything in [Entities](/docs/editor/editor/entities), [Components](/docs/editor/editor/components) and [Systems](/docs/editor/editor/systems) works the same way.
+
+The entities and systems of `main.ts` and of the scene's parents are shown too, greyed and read-only: they are in the game whenever this scene is. Right-click one to open it in code, or _Edit this scene_ to switch to it.
+
+A scene whose `setup` comes from a base class, or that spawns entities in a loop, is shown read-only.
+
+## Scene vars
+
+The **Vars** panel lists the vars that scenes and systems share (`ctx.scenes.vars`), as declared in the app's `scene-vars.ts`:
+
+```ts
+declare module '@nanoforge-dev/scene' {
+ interface SceneVars {
+ /** Balls left in the current game. @default 3 */
+ lives: number;
+ }
+}
+```
+
+- Each var shows its type, its default, its description, the scenes that make it (`init`, its possible owners), and its uses: click it to list them, and click a use to open it.
+- **Add var** asks for its name, type, default and description; the file is created with the first var.
+- _Rename_ changes the declaration and every `vars.get("…")`, `vars.set("…")`… of that var. _Change type_, _Change default_ and _Change description_ edit the declaration; _Remove_ removes it, after a warning when the code uses it (_Remove anyway_).
+- A var used in code but not declared is listed under _Used but not declared_, with **Declare**.
+
+A var belongs to the scene that made it, and goes away when that scene is unloaded, unless it is persistent.
+
+## While the game plays
+
+- **Scenes**: the loaded scenes are marked, and the current one says so. Right-click a scene: _Load scene_ (the editor asks for its params), _Load under the current scene_ for a scene without a parent (a pause menu), _Unload scene_.
+- **Vars**: each var shows its value in the running game and the scene it belongs to. _Set live value…_ changes it in the game. Vars that only the running game has are listed too.
+- **Hierarchy**: the running game's entities are grouped under the scene that spawned them. _Apply to code_ writes a change into that scene's file.
+
+These change the running game only, never the code.
+
+The example project `examples/breakout` (in the editor repository) is a game made of scenes.
diff --git a/docs/editor/editor/settings.mdx b/docs/editor/editor/settings.mdx
new file mode 100644
index 0000000..5acd771
--- /dev/null
+++ b/docs/editor/editor/settings.mdx
@@ -0,0 +1,64 @@
+---
+title: 'Settings and shortcuts'
+icon: 'sliders-horizontal'
+description: 'Change the editor settings, where they are saved, and the keyboard shortcuts'
+---
+
+Open the settings with _File › Settings…_ or `Ctrl+Alt+S` (also `Ctrl+,`).
+
+
+
+Categories are on the left, their settings on the right. The search box looks through every category. Changes wait until you press **Apply** or **OK**. **Cancel** (or `Escape`) asks before dropping them.
+
+## Where a setting is saved
+
+Each setting has a small menu that chooses where your change goes:
+
+| Scope | Saved | Use it for |
+| --------------------- | ------------------------------------------------ | ----------------------------------- |
+| **Account** | With your account | Your preferences, wherever you work |
+| **This machine** | In this browser | What depends on this computer |
+| **Project** | In `.nanoforge/editor/settings.json`, committed | What the whole team should share |
+| **Project (only me)** | In `.nanoforge/editor/local.json`, not committed | Your preferences for this project |
+
+When several scopes have a value, the more specific one wins: Project (only me), then Project, This machine, Account. The **inspect** popover of a setting shows its value in each scope and resets one.
+
+_Edit as JSON_ opens the project's settings file in the code editor, with completion.
+
+## Files kept in the browser
+
+The editor keeps the files of the projects you open in your browser, so opening one again downloads only what changed. A file that several projects or branches have is kept once.
+
+_Editor › Storage_ shows the space each project takes, with **Clear** for one project and **Clear all**. **Cache size** (500 MB) and **Forget projects after** (30 days) are saved on this machine: the least recently used files go first, and the editor never takes more than a tenth of what the browser allows. Removing a project from _Recent_ also clears its files. Clearing only drops these copies: unsaved changes and undo history are kept apart and never cleared. Switch on **Keep these files when the browser runs short of space** so the browser does not remove them on its own.
+
+In the online editor, signing in as someone else on the same browser removes the previous user's files.
+
+## Import and export
+
+The _Import & export_ page saves a scope to a `.json` file, and loads one with a preview of what would change.
+
+## Appearance
+
+_Settings › Editor › Appearance_ shows each theme as a card in its own colors: click one, then **Apply**. **Density** makes panels, rows and buttons tighter or roomier. **Icons** chooses an icon theme. **Get more themes** opens the marketplace on the plugins that are themes (`keywords:theme`).
+
+## Keyboard shortcuts
+
+The _Keyboard shortcuts_ page lists every action with its shortcuts.
+
+
+
+- **Search** by name or by shortcut (`ctrl+s`). The filters show only what you changed, or conflicts.
+- **Add shortcut** on an action, then press the keys. Press a second combination to make a chord (`Ctrl+K` then `Ctrl+S`). A shortcut starts with `Ctrl`, `Alt` or `⌘`, or is a function key (`F1` to `F12`): a plain key would no longer work while typing. A plain key is accepted when the condition needs `!textInputFocus` (as in `focusedWidget == 'file-manager.files' && !textInputFocus`, not under `||`): the shortcut then never fires in a text field or the code editor.
+- When the shortcut is already used, the dialog names the other action: keep both, replace, or cancel.
+- **Reset** puts an action back to its default.
+- A **preset** changes many shortcuts at once: _NanoForge_ (the defaults), _VS Code_, _Godot_, _IntelliJ_ (Shift twice for the command palette, Ctrl+K to commit, Alt+0 for the Commit window; the browser keeps Alt+1…9 for its tabs, so the preset leaves them out). Your own changes apply on top.
+
+Shortcuts are saved to your account, or to this machine only.
+
+## Plugins
+
+The _Plugins_ page lists the plugins, turns one off, and installs more: see [Plugins and packages](/docs/editor/editor/plugins-and-packages).
+
+## Sync
+
+The top of the dialog shows the state of the account sync. After working offline on two devices, a _Sync conflicts_ page lets you choose, for each setting changed on both, which value to keep.
diff --git a/docs/editor/editor/systems.mdx b/docs/editor/editor/systems.mdx
new file mode 100644
index 0000000..1a1e740
--- /dev/null
+++ b/docs/editor/editor/systems.mdx
@@ -0,0 +1,47 @@
+---
+title: 'Systems'
+icon: 'cog'
+description: 'Create systems, choose which ones an app runs and in which order'
+---
+
+Systems hold the logic of the game. A system is a function the engine calls at every tick, with the entities that have the components it asks for.
+
+```ts
+/**
+ * Moves entities by their velocity.
+ * @system
+ */
+export const move = (registry: Registry, ctx: Context) => {
+ // …
+};
+```
+
+An app runs the systems its `main.ts` adds, in that order:
+
+```ts
+registry.addSystem(move);
+registry.addSystem(draw);
+```
+
+## The Systems panel
+
+The **Systems** panel lists the systems the selected app runs, **in run order**, with the components each one reads.
+
+| To | Do |
+| ---------------- | ---------------------------------------------------------------------------------------------------------------------- |
+| Add a system | **Add system**, then choose one the app can use. Its import is added. |
+| Change the order | Drag a system up or down, or `Alt+Up` / `Alt+Down` (right-click › Run earlier, Run later): the `addSystem` lines move. |
+| Remove | **Remove from app** on its row (_Remove from scene_ while a [scene](/docs/editor/editor/scenes) is edited). The system's file stays. |
+| See its code | _Open in code_ |
+
+## Create a system
+
+In the **Components** panel, **New › New system in app**, then a name. The file is created in the app's systems folder and opens in the code editor. Add it to the app from the Systems panel, or with **Add to app** in the Components panel (**Add to scene** while a [scene](/docs/editor/editor/scenes) is edited).
+
+Systems can live in a shared library or come from a package, like [components](/docs/editor/editor/components#share-between-client-and-server).
+
+## While the game plays
+
+Each running system has a switch: turn one off to see the game without it. This changes the running game only, and is reset when the game stops.
+
+The **Profiler** shows the time each system takes: see [Play the game](/docs/editor/editor/play#inspect-the-running-game).
diff --git a/docs/editor/getting-started/create-your-first-project.mdx b/docs/editor/getting-started/create-your-first-project.mdx
new file mode 100644
index 0000000..a52c150
--- /dev/null
+++ b/docs/editor/getting-started/create-your-first-project.mdx
@@ -0,0 +1,59 @@
+---
+title: 'Create your first project'
+icon: 'book'
+description: 'Create a project and open it in the editor'
+---
+
+## Online
+
+Create a project from the [Project Dashboard](https://projects.nanoforge.eu/dashboard/projects). Click **New project** and fill in the project information.
+
+
+
+To link the project to a GitHub repository, click **Add repositories from github** and select the organization to use.
+
+Once the project is created, click **Open Editor**. The first time, a page asks for the programming language and whether the game is single-player or multiplayer.
+
+
+
+## On your machine
+
+With the NanoForge CLI:
+
+```sh
+nf new # asks for a name, a language, and whether the game has a server
+nf editor my-game # starts the editor and opens the project in your browser
+```
+
+`nf editor` without a path opens the list of recent projects. The first time a folder is opened, the editor asks whether you trust it. A trusted folder's code runs on your computer: its `nanoforge.config.ts`, its plugins, its builds and games, its Prettier and its Git hooks. **Open in restricted mode** keeps all of that off: you can read and edit the project, and **Trust this folder** (in the notification, or the command palette) turns it on later. Projects you create with **New project** are trusted. A local editor works on the folder itself: what you change in the editor is on your disk at once, and what you change on disk shows in the editor.
+
+A local editor can do what a hosted one cannot: run the game, use Git with your own credentials, and install plugins and packages.
+
+On a computer other people use too, an editor started directly from its build (`EDITOR_TOKEN=random pnpm start` in `apps/editor` of the editor repository) answers only to the link it prints when it starts (it ends with `?token=…`), so the others can't reach your projects through its port. Don't set it with `nf editor`: the browser it opens has no token, and the editor refuses it. The browser keeps the token in a cookie, which it also sends to the other local ports of the computer: any server listening on one of them, another user's too, gets it when this browser visits it.
+
+## The tutorial
+
+New to the editor? Its home page offers **Start the tutorial** (and _Help › Tutorial_ plays it again at any time). A local editor makes a small game, `my-first-game`, in the folder it works on: an orange ball that should bounce, and one mistake that keeps it still. A tour then walks you through the editor while you fix it: the screens, adding an entity, changing a value, fixing the mistake from **Problems**, playing the game, looking into it with **World**, and a first Git commit.
+
+In a hosted editor, open one of your projects first: _Help › Tutorial_ shows the screens, adding an entity, changing a value and editing the code.
+
+## The editor
+
+
+
+- **Top**: the menu bar, the four main **screens** (Project, Scene, Script, Game), and the **Play** button.
+- **Left**: **Files**, the **Hierarchy** of entities and, for games made of scenes, **Scenes**.
+- **Right**: the **Inspector**.
+- **Bottom**: the **Console**.
+
+- **Status bar**: the project, the count of problems, the Git branch, and the game's speed while it plays.
+
+The editor starts with these main panels only. _View › Layouts › All panels_ adds the others: **Commit**, **Components** and **Systems** on the left, **Problems**, **Git**, and the **Profiler**, **Network** and **World** panels at the bottom. _View › Panels_ opens any one of them, and the **History** of changes.
+
+Every panel can be moved, floated or closed: see [Layout](/docs/editor/editor/layout).
+
+## Next
+
+1. Open the **Scene** screen and select an entity in the **Hierarchy**: its components show in the **Inspector**. See [Entities](/docs/editor/editor/entities).
+2. Press **Play** (`F5`). See [Play the game](/docs/editor/editor/play).
+3. Open `apps/client/src/main.ts` from **Files**. See [Code editor](/docs/editor/editor/code-editor).
diff --git a/docs/editor/getting-started/introduction.mdx b/docs/editor/getting-started/introduction.mdx
new file mode 100644
index 0000000..62a1519
--- /dev/null
+++ b/docs/editor/getting-started/introduction.mdx
@@ -0,0 +1,31 @@
+---
+title: 'Editor'
+icon: 'book'
+description: 'NanoForge Editor documentation'
+---
+
+The NanoForge editor is where you build a NanoForge game: its files, its code, its entities, components and systems, and the game itself, running next to them. It runs in the browser, either hosted or on your machine with `nf editor`.
+
+A NanoForge game is **code**. The editor does not keep a scene file of its own: when you add an entity or change a value, it edits your `main.ts`, and what you write by hand shows in its panels.
+
+
+
+## Start here
+
+- [Create your first project](/docs/editor/getting-started/create-your-first-project)
+- [Find your way around](/docs/editor/editor/overview)
+
+## Using the editor
+
+- [Layout](/docs/editor/editor/layout): panels, screens, saved layouts
+- [Files](/docs/editor/editor/files)
+- [Code editor](/docs/editor/editor/code-editor)
+- [Entities](/docs/editor/editor/entities), [Components](/docs/editor/editor/components) and [Systems](/docs/editor/editor/systems)
+- [Play the game](/docs/editor/editor/play): play modes, the Game screen, the console, live editing
+- [Settings and shortcuts](/docs/editor/editor/settings)
+- [Git](/docs/editor/editor/git)
+- [Plugins and packages](/docs/editor/editor/plugins-and-packages)
+
+## Extending the editor
+
+- [Plugins](/docs/editor/plugins/overview): write your own panels, commands and tools
diff --git a/docs/editor/images/code-editor.png b/docs/editor/images/code-editor.png
new file mode 100644
index 0000000..bf43198
Binary files /dev/null and b/docs/editor/images/code-editor.png differ
diff --git a/docs/editor/images/command-palette.png b/docs/editor/images/command-palette.png
new file mode 100644
index 0000000..4ad0059
Binary files /dev/null and b/docs/editor/images/command-palette.png differ
diff --git a/docs/editor/images/create-project.png b/docs/editor/images/create-project.png
new file mode 100644
index 0000000..546425d
Binary files /dev/null and b/docs/editor/images/create-project.png differ
diff --git a/docs/editor/images/ecs-components.png b/docs/editor/images/ecs-components.png
new file mode 100644
index 0000000..0b637cb
Binary files /dev/null and b/docs/editor/images/ecs-components.png differ
diff --git a/docs/editor/images/ecs-scene.png b/docs/editor/images/ecs-scene.png
new file mode 100644
index 0000000..3892c5f
Binary files /dev/null and b/docs/editor/images/ecs-scene.png differ
diff --git a/docs/editor/images/editor-overview.png b/docs/editor/images/editor-overview.png
new file mode 100644
index 0000000..23d133b
Binary files /dev/null and b/docs/editor/images/editor-overview.png differ
diff --git a/docs/editor/images/game-playing.png b/docs/editor/images/game-playing.png
new file mode 100644
index 0000000..faca79f
Binary files /dev/null and b/docs/editor/images/game-playing.png differ
diff --git a/docs/editor/images/init-project.png b/docs/editor/images/init-project.png
new file mode 100644
index 0000000..be7539c
Binary files /dev/null and b/docs/editor/images/init-project.png differ
diff --git a/docs/editor/images/keyboard-shortcuts.png b/docs/editor/images/keyboard-shortcuts.png
new file mode 100644
index 0000000..a6080ff
Binary files /dev/null and b/docs/editor/images/keyboard-shortcuts.png differ
diff --git a/docs/editor/images/packages.png b/docs/editor/images/packages.png
new file mode 100644
index 0000000..9e28d52
Binary files /dev/null and b/docs/editor/images/packages.png differ
diff --git a/docs/editor/images/plugins-marketplace.png b/docs/editor/images/plugins-marketplace.png
new file mode 100644
index 0000000..2cc14ca
Binary files /dev/null and b/docs/editor/images/plugins-marketplace.png differ
diff --git a/docs/editor/images/profiler.png b/docs/editor/images/profiler.png
new file mode 100644
index 0000000..a3bc56c
Binary files /dev/null and b/docs/editor/images/profiler.png differ
diff --git a/docs/editor/images/settings.png b/docs/editor/images/settings.png
new file mode 100644
index 0000000..52994cb
Binary files /dev/null and b/docs/editor/images/settings.png differ
diff --git a/docs/editor/navigation.json b/docs/editor/navigation.json
new file mode 100644
index 0000000..34f7e44
--- /dev/null
+++ b/docs/editor/navigation.json
@@ -0,0 +1,46 @@
+[
+ {
+ "group": "Getting started",
+ "icon": "rocket",
+ "pages": [
+ "docs/editor/getting-started/introduction",
+ "docs/editor/getting-started/create-your-first-project"
+ ]
+ },
+ {
+ "group": "Using the editor",
+ "icon": "pen-ruler",
+ "pages": [
+ "docs/editor/editor/overview",
+ "docs/editor/editor/adapt-a-project",
+ "docs/editor/editor/layout",
+ "docs/editor/editor/files",
+ "docs/editor/editor/code-editor",
+ "docs/editor/editor/entities",
+ "docs/editor/editor/components",
+ "docs/editor/editor/systems",
+ "docs/editor/editor/scenes",
+ "docs/editor/editor/play",
+ "docs/editor/editor/settings",
+ "docs/editor/editor/git",
+ "docs/editor/editor/plugins-and-packages"
+ ]
+ },
+ {
+ "group": "Plugins",
+ "icon": "puzzle-piece",
+ "pages": [
+ "docs/editor/plugins/overview",
+ "docs/editor/plugins/create-your-first-plugin",
+ "docs/editor/plugins/manifest",
+ "docs/editor/plugins/sdk",
+ "docs/editor/plugins/extension-points",
+ "docs/editor/plugins/widgets-and-styles",
+ "docs/editor/plugins/themes",
+ "docs/editor/plugins/settings",
+ "docs/editor/plugins/history",
+ "docs/editor/plugins/code-and-codegen",
+ "docs/editor/plugins/engine-libs"
+ ]
+ }
+]
diff --git a/docs/editor/plugins/code-and-codegen.mdx b/docs/editor/plugins/code-and-codegen.mdx
new file mode 100644
index 0000000..57f590f
--- /dev/null
+++ b/docs/editor/plugins/code-and-codegen.mdx
@@ -0,0 +1,137 @@
+---
+title: 'Code and code generation'
+icon: 'braces'
+description: 'Read the game code, change it safely, and describe items such as components and systems'
+---
+
+A NanoForge game is code: there is no scene file beside it. A plugin that shows or edits something of the game reads the code and writes code. The editor gives three tools for that.
+
+| Tool | Runs in | Does |
+| ------------------ | --------------- | --------------------------------------------------------------------- |
+| **Analyzer** | the code worker | Reads a file's syntax tree and returns a model (plain data). |
+| **Transformer** | the code worker | Changes the syntax tree; the editor turns it into text edits. |
+| **Codegen target** | the page | Ties both together for an app: a live model, and undoable operations. |
+
+The code worker holds the project's files in memory, with unsaved edits, and TypeScript. It is the only place where the compiler is loaded.
+
+## A worker entry
+
+Add a second entry to the manifest and to the build.
+
+```json
+"entry": { "client": "index.js", "worker": "worker.js" }
+```
+
+```ts
+// vite.config.ts
+build: { lib: { entry: { index: 'src/index.ts', worker: 'src/worker.ts' }, formats: ['es'] } }
+```
+
+```ts
+// src/worker.ts
+import { defineWorkerPlugin } from '@nanoforge-dev/editor-sdk/worker';
+
+export default defineWorkerPlugin({
+ activate(sdk) {
+ sdk.registerAnalyzer('counter.exports', ({ file }) => file.getExportedDeclarations().size);
+ sdk.registerTransformer('counter.addComment', ({ file, edit }, op) => {
+ edit.insertAt(0, `// ${(op as { text: string }).text}\n`);
+ });
+ },
+});
+```
+
+The context of an analyzer has:
+
+| Member | Is |
+| --------------------------- | ------------------------------------------------------------------------------------------ |
+| `path`, `text` | The file's project path and its current text. |
+| `file`, `project` | The ts-morph `SourceFile` and `Project`. ts-morph comes from the editor: do not bundle it. |
+| `ref(node)`, `resolve(ref)` | A stable reference of a node, to send to the page and get the node back later. |
+| `literals` | Helpers between literals in code and values (`literalToValue`, `valueToLiteral`…). |
+
+A transformer also gets `edit`, which records the changes: `replace(node, text)`, `insertBefore`, `insertAfter`, `insertAt(offset, text)`, `remove(node)`, `removeLines(node)`.
+
+## Call them from the page
+
+```ts
+import { CodeServiceToken } from '@nanoforge-dev/editor-sdk';
+
+const code = context.services.get(CodeServiceToken);
+
+const count = await code.analyze('apps/client/src/main.ts', 'counter.exports');
+
+// An undoable command, applied through the document service:
+const command = await code.edit(
+ 'apps/client/src/main.ts',
+ 'counter.addComment',
+ { text: 'hi' },
+ {
+ label: 'Add a comment',
+ },
+);
+```
+
+`code.edit` returns a `HistoryCommand` (or `undefined` when nothing changes). Push it on the file's history, or group several in a transaction: see [history](/docs/editor/plugins/history).
+
+The model an analyzer returns crosses to the page as plain data: no syntax nodes, no functions.
+
+## Codegen targets
+
+A **codegen target** is how one kind of app keeps part of its state in code. The ECS plugin's target reads an app's entry file as a list of entities, components and systems, and writes back operations such as "add a component to this entity".
+
+```ts
+import { CODEGEN_TARGETS, type CodegenTarget } from '@nanoforge-dev/editor-sdk';
+
+const target: CodegenTarget = {
+ id: 'counter.target',
+ label: 'Counter',
+ priority: 0,
+ appliesTo: (app) => app.type === 'client',
+ load: (app) => modelOf(app), // Observable, re-read on change
+ apply: (app, op) => commandFor(app, op), // Promise
+};
+context.subscriptions.add(context.contribute(CODEGEN_TARGETS, target));
+```
+
+- When several targets apply to an app, the highest `priority` wins (`selectTarget`).
+- The Scene screen shows the editor a plugin contributed to `SCENE_EDITORS` for the target in use.
+- To make the ECS widgets (hierarchy, inspector, systems, 2D scene) edit another place than the entry file's `main`, contribute to the ECS plugin's `ecs.sources` instead: a location is a file and a function body (`{ kind: 'method', class: 'Level1', method: 'setup' }`), and the widgets keep working unchanged. The scene plugin edits the selected scene's `setup` this way.
+
+## Item owners
+
+**Items** are exports of the game's code that the editor lists: components, systems, and whatever a plugin describes. The editor extracts for each one its name, documentation, constructor parameters and fields, with their types and defaults, from the code and its TSDoc.
+
+What an item _is_ belongs to a plugin, its **owner**. The ECS plugin owns the `@component` and `@system` tags; the core knows nothing about them.
+
+```json
+"contributes": { "itemOwner": { "schema": 1, "tags": ["widget"] } }
+```
+
+```ts
+// worker entry
+sdk.registerItemOwner({
+ name: '@acme/widgets',
+ version: '0.1.0',
+ schema: 1,
+ tags: ['widget'],
+ extract: ({ tags }) => (tags.widget ? { kind: 'widget' } : undefined),
+});
+```
+
+`extract` returns the plugin's own data about an export, stored under the plugin's name. Read items in the page with the catalog:
+
+```ts
+import { CatalogServiceToken, ownerObjects } from '@nanoforge-dev/editor-sdk';
+
+const catalog = context.services.get(CatalogServiceToken);
+catalog.state.subscribe(({ items }) => {
+ const mine = items.filter((item) => ownerObjects(item.meta)['@acme/widgets']);
+});
+```
+
+Items come from the project's apps, its shared libraries and its installed packages (`nf_modules`, read-only). The catalog keeps a cache in `.nanoforge/editor/cache/meta/` and extracts again only what changed.
+
+## Problems
+
+A plugin reports problems (shown in the Problems panel and in the code editor) through `DiagnosticsServiceToken`, and JSON files get completion and validation from a schema contributed to `JSON_SCHEMAS`.
diff --git a/docs/editor/plugins/create-your-first-plugin.mdx b/docs/editor/plugins/create-your-first-plugin.mdx
new file mode 100644
index 0000000..7b9000f
--- /dev/null
+++ b/docs/editor/plugins/create-your-first-plugin.mdx
@@ -0,0 +1,193 @@
+---
+title: 'Create your first plugin'
+icon: 'rocket'
+description: 'Scaffold a plugin with nf create plugin, run it in the editor and change it'
+---
+
+This page builds **Counter**, a small plugin with a panel, a command, a setting and an action you can undo. The finished plugin is in the editor repository, under `examples/counter-plugin`.
+
+## 1. Create it
+
+```sh
+nf create plugin --name @acme/counter
+```
+
+The name is the plugin's name in the registry: `@scope/name`, in lowercase. The command writes a `counter` folder (`--path` chooses another one); it does not need a NanoForge project around it.
+
+```text
+counter/
+├── nanoforge.manifest.json what the plugin adds to the editor
+├── package.json
+├── vite.config.ts builds dist/
+├── svelte.config.js
+├── tsconfig.json
+└── src/
+ ├── index.ts activate()
+ ├── counter.ts the plugin's state
+ └── Panel.svelte the panel
+```
+
+## 2. Run it in the editor
+
+```sh
+cd counter
+pnpm install
+pnpm dev # rebuilds dist/ on every change
+```
+
+In another terminal, start the editor with the plugin as a **dev plugin**:
+
+```sh
+DEV_PLUGINS=/path/to/counter nf editor /path/to/a/project
+```
+
+The Counter panel is in the bottom right dock. In the simple layout, which shows only the main panels, open it with _View › Panels › Counter_ (or _View › Layouts › All panels_); the same entry shows it again once closed. A plugin can put its panel in the simple layout with `"essential": true`, for the few panels most work needs. When you save a source file, the editor reloads the plugin without reloading the page.
+
+
+ `@nanoforge-dev/editor-sdk` and `@nanoforge-dev/editor-vite-plugin` are not published on npm yet,
+ so `pnpm install` fails on them. Until they are, point both at a checkout of the editor repository
+ in the plugin's `package.json` (`"link:/path/to/editor/packages/sdk"` and
+ `"link:/path/to/editor/tooling/vite-plugin"`): `examples/README.md` in that repository has the
+ steps.
+
+
+## 3. The manifest
+
+`nanoforge.manifest.json` declares what the plugin adds. The editor reads it before running any code.
+
+```json
+{
+ "type": "plugin",
+ "name": "@acme/counter",
+ "version": "0.1.0",
+ "displayName": "Counter",
+ "engines": { "editor": ">=0.1.0" },
+ "entry": { "client": "index.js" },
+ "activation": ["onWidget:counter.panel", "onCommand:counter.add"],
+ "contributes": {
+ "widgets": [
+ {
+ "id": "counter.panel",
+ "title": "Counter",
+ "icon": "plus",
+ "defaultSlot": "rightBottom",
+ "order": 900
+ }
+ ],
+ "commands": [{ "id": "counter.add", "title": "Add to the counter", "category": "Counter" }],
+ "menus": [{ "menu": "edit", "command": "counter.add", "group": "counter" }],
+ "settings": [
+ { "key": "step", "type": "number", "default": 1, "title": "Step", "category": "Counter" }
+ ]
+ }
+}
+```
+
+- `activation`: the plugin's code loads when its panel is first shown or its command first runs.
+- `widgets`: a panel named Counter, docked bottom right by default.
+- `commands` and `menus`: a command, listed in the Edit menu and in the command palette (`Ctrl+Shift+P`).
+- `settings`: a number shown in _Settings › Counter_. Its full key is `@acme/counter.step`.
+
+## 4. The code
+
+`src/index.ts` exports the plugin. `activate` gets a **context**: the editor's services, and `subscriptions`, where you put everything the plugin adds so it is removed with the plugin.
+
+```ts
+import type { Component } from 'svelte';
+
+import { HistoryServiceToken, SettingsServiceToken, definePlugin } from '@nanoforge-dev/editor-sdk';
+import { StyleServiceToken, WIDGET_VIEWS, type WidgetInstance } from '@nanoforge-dev/editor-sdk/ui';
+
+import Panel from './Panel.svelte';
+import { count } from './counter';
+
+/** Undo and redo target of the panel. */
+export const HISTORY = 'counter';
+
+export default definePlugin({
+ async activate(context) {
+ const { services } = context;
+
+ // Styles are built into counter.css: inject them when the plugin starts.
+ const css = await fetch(context.resolveAsset('counter.css')).then((r) =>
+ r.ok ? r.text() : '',
+ );
+ context.subscriptions.add(services.get(StyleServiceToken).inject(context.name, css));
+
+ // The view of the widget declared in the manifest.
+ context.subscriptions.add(
+ context.contribute(WIDGET_VIEWS, {
+ id: 'counter.panel',
+ component: Panel as Component<{ instance: WidgetInstance }>,
+ }),
+ );
+
+ // A history of its own, so each addition can be undone.
+ const history = services
+ .get(HistoryServiceToken)
+ .registerContext({ id: HISTORY, label: 'Counter', owner: context.name });
+ context.subscriptions.add(history);
+
+ const settings = services.get(SettingsServiceToken);
+ context.subscriptions.add(
+ context.registerCommand('counter.add', async () => {
+ const step = Number(settings.get('@acme/counter.step')) || 1;
+ await history.stack.push({
+ label: `Add ${step}`,
+ do: () => count.set(count.get() + step),
+ undo: () => count.set(count.get() - step),
+ });
+ }),
+ );
+ },
+});
+```
+
+`src/Panel.svelte` is a Svelte 5 component. It receives the widget **instance**, and uses the editor's own `Button`.
+
+```svelte
+
+
+
+
{$count}
+
+
+```
+
+`count` is an `ObservableValue` from the SDK: Svelte reads it as a store (`$count`).
+
+## 5. Try it
+
+- Click **Add** twice, then press `Ctrl+Z` with the panel focused: the counter goes back by one. The step is in the History panel too.
+- Run _Edit › Add to the counter_, or find it in the command palette.
+- Change _Settings › Counter › Step_ to 5 and add again.
+
+## 6. Install it without the dev mode
+
+```sh
+pnpm build
+```
+
+Copy `dist/` to `~/.nanoforge/editor/plugins/@acme/counter` (every project) or to `/.nanoforge/plugins/@acme/counter` (one project, and it can be committed with it). Reload the editor.
+
+## Where to go next
+
+- A shortcut for the command: `contributes.keybindings` in the [manifest](/docs/editor/plugins/manifest).
+- A status bar item, a file template, a toolbar button: [extension points](/docs/editor/plugins/extension-points).
+- Reading and changing the game's code: [code and code generation](/docs/editor/plugins/code-and-codegen).
+- A plugin that only makes sense with an engine library: [engine libraries](/docs/editor/plugins/engine-libs).
diff --git a/docs/editor/plugins/engine-libs.mdx b/docs/editor/plugins/engine-libs.mdx
new file mode 100644
index 0000000..87aff1b
--- /dev/null
+++ b/docs/editor/plugins/engine-libs.mdx
@@ -0,0 +1,97 @@
+---
+title: 'Engine libraries'
+icon: 'cpu'
+description: 'Plugins that depend on an engine library, and talking to the running game'
+---
+
+A NanoForge game is made of apps (a client, a server), and each app uses **engine libraries**: `@nanoforge-dev/ecs`, `@nanoforge-dev/graphics-2d`, `@nanoforge-dev/network`… A plugin for the ECS means nothing in an app without it.
+
+## Say what the plugin needs
+
+```json
+"engineLibs": {
+ "required": { "@nanoforge-dev/ecs": "*" },
+ "optional": { "@nanoforge-dev/graphics-2d": "^1.0.0" }
+}
+```
+
+- `required`: an app must have these libraries (in these version ranges) for the plugin to apply to it.
+- `optional`: libraries the plugin can use when they are there.
+
+The plugin is still loaded in a project where no app has them: it decides what to show.
+
+## Apps the plugin applies to
+
+```ts
+import { observe } from '@nanoforge-dev/editor-sdk';
+
+context.subscriptions.add(
+ observe(context.eligibleApps, (apps) => {
+ // the project's apps that have every required library; changes when the project does
+ }),
+);
+```
+
+Each app has its `id`, `name`, `type` (`client`, `server`, or `lib` for a shared library) and `engineLibs` (name to installed version). `missingEngineLibs(manifest, app)` lists what an app lacks, and `isEligible(manifest, app)` answers yes or no.
+
+### In `when` clauses
+
+| Key | True when |
+| ------------------------------- | --------------------------------------------- |
+| `engineLib:` | the active app has that library |
+| `plugin..eligible` | the active app has what that plugin requires |
+| `activeApp` | (a value) the id of the app the user works on |
+
+```json
+{ "id": "ecs.addEntity", "title": "Add entity", "when": "engineLib:@nanoforge-dev/ecs" }
+```
+
+## The running game
+
+`RuntimeServiceToken` is the game the editor plays.
+
+```ts
+import { RuntimeServiceToken, isPlaying } from '@nanoforge-dev/editor-sdk';
+
+const runtime = context.services.get(RuntimeServiceToken);
+runtime.session.subscribe(({ state }) => {
+ if (isPlaying(state)) {
+ /* building, starting, running, paused */
+ }
+});
+```
+
+Commands: `runtime.play`, `runtime.pause`, `runtime.resume`, `runtime.step`, `runtime.restart`, `runtime.stop`. The session also says which apps play, in which mode, and whether the game can be paused (`controllable`). Context keys: `runtime.active`, `runtime.state`, `runtime.controllable`.
+
+### Asking the engine for data
+
+The engine sends nothing unless asked. A plugin asks for **features**, and gets **events** while the game runs.
+
+```ts
+const request = runtime.useFeatures({ frameStats: { intervalMs: 250 } });
+const events = runtime.onEvent(({ source, app, event, args }) => {
+ // source: 'client' or 'server'; app: the app's id
+ if (event === 'frame-stats') {
+ /* args[0]: the stats of that window */
+ }
+});
+// later
+request.dispose();
+events.dispose();
+```
+
+| Feature | Events | Carries |
+| ------------------------------------------ | -------------------------------- | ---------------------------------------------------------------- |
+| `frameStats: { intervalMs }` | `frame-stats` | Tick time and time per library, per window. |
+| `logs: { values: true }` | lines through `runtime.onLog` | Console lines with the logged values and where they were logged. |
+| `networkTrace: { maxPerSecond, maxBytes }` | `network-trace`, `network-stats` | Packets, and totals every second. |
+| `ecsWorld: { intervalMs }` | `ecs-world` | Entities and components of the live world. |
+| `ecsSystemStats: { intervalMs }` | `ecs-system-stats` | Time per ECS system. |
+
+- Requests of every plugin are merged; the most demanding one wins. **Dispose your request when your panel is hidden**: ask in an effect on `instance.visible`, not when the plugin starts.
+- An older engine ignores features it does not know: handle the absence of events.
+- The game only runs in a local editor. A hosted editor never builds or runs project code.
+
+### Game output
+
+Everything the game prints goes to the editor's logger, under the sources `game:client` and `game:server`. A plugin's own `context.logger` lines show under _Plugins_.
diff --git a/docs/editor/plugins/extension-points.mdx b/docs/editor/plugins/extension-points.mdx
new file mode 100644
index 0000000..a9d3eb0
--- /dev/null
+++ b/docs/editor/plugins/extension-points.mdx
@@ -0,0 +1,118 @@
+---
+title: 'Extension points'
+icon: 'blocks'
+description: 'Every place where a plugin can add something to the editor'
+---
+
+An **extension point** is a typed list the editor reads. A plugin adds a value with `context.contribute(POINT, value)` and keeps the returned disposable in `context.subscriptions`.
+
+```ts
+import { STATUS_BAR_ITEMS } from '@nanoforge-dev/editor-sdk/ui';
+
+context.subscriptions.add(
+ context.contribute(STATUS_BAR_ITEMS, {
+ id: 'counter.total',
+ alignment: 'right',
+ text: derived([count], (value) => `Count: ${value}`),
+ command: 'counter.add',
+ }),
+);
+```
+
+Several points can also be filled from the [manifest](/docs/editor/plugins/manifest#contributions), without code: widgets, menus, keybindings, keymap presets, settings, themes, tours and document editors.
+
+## Workbench
+
+From `@nanoforge-dev/editor-sdk/ui`.
+
+| Point | A value is | Manifest key |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------- | --------------- |
+| `WIDGETS` | A panel or a screen: `id`, `title`, `icon`, `kind`, `defaultSlot`, `order`… | `widgets` |
+| `WIDGET_VIEWS` | The view of a widget: `{ id, component }` (a Svelte component) or `{ id, mount(element, instance) }` for another framework. | |
+| `MENU_BAR` | A menu of the menu bar: `{ id, title, order }`. | |
+| `MENU_ITEMS` | An entry of a menu, a submenu or a context menu. | `menus` |
+| `KEYBINDINGS` | A default shortcut: `{ key, command, when, args }`. | `keybindings` |
+| `KEYMAP_PRESETS` | A named set of shortcuts. | `keymapPresets` |
+| `TOOLBAR_ITEMS` | A button of the top bar: `{ id, icon, title, command, when, toggled }`. | |
+| `STATUS_BAR_ITEMS` | An item of the status bar: `{ id, alignment, text, tooltip, command, when }`. `text` is an observable. | |
+| `SETTINGS_PAGES` | A page of the Settings dialog with its own editor. It names the settings it edits, which then leave the category list. | |
+| `THEMES` | A color theme. | `themes` |
+| `TOURS` | A guided tour: steps over the editor, ahead on real events. `TourServiceToken` starts one. | `tours` |
+
+## Files
+
+| Point | A value is |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `FILE_TEMPLATES` | A "New…" entry of the Files panel: `{ id, title, category, when, defaultName, create({ folder, name }) }` returning the files to write. `when` sees `fileFolder` and `appType` (`client`, `server`, `lib`, empty outside apps). |
+| `FILE_ACTIONS` | An entry of the context menu of files: `{ id, title, command, group, when }`. The command gets the selected paths. `when` sees `fileKind`, `fileExtname`, `fileReadOnly`, `fileSelectionCount`. |
+| `FILE_ICONS` | The icon of files matching a glob: `{ pattern, icon, priority }`. |
+| `FILE_DECORATIONS` | Marks on files (a badge and a tone), as Git does: `{ id, changes, decorate(path, kind) }`. |
+
+## Code
+
+| Point | A value is | From |
+| ------------------------- | ------------------------------------------------------------------------------------------------------ | --------- |
+| `DOCUMENT_EDITORS` | Opens files matching a glob with a widget (manifest key `documentEditors`). | SDK |
+| `JSON_SCHEMAS` | A JSON schema for files matching globs: completion and validation in the code editor. | SDK |
+| `CODEGEN_TARGETS` | A way to read and change an app's code as a model. See [code and code generation](/docs/editor/plugins/code-and-codegen). | SDK |
+| `CODE_EDITOR_SIDE_PANELS` | A panel beside the code editor for some files: `{ id, title, component, appliesTo(path) }`. | SDK `/ui` |
+
+## Game and Scene screens
+
+| Point | A value is |
+| ------------------- | --------------------------------------------------------------------------------------- |
+| `VIEWPORT_TOOLS` | A button of the Game or Scene toolbar: `{ id, screen, icon, title, command, toggled }`. |
+| `VIEWPORT_OVERLAYS` | A component drawn over the running game or the scene (gizmos, debug views). |
+| `SCENE_EDITORS` | The content of the Scene screen for a code generation target. |
+
+## Project
+
+From `@nanoforge-dev/editor-sdk`.
+
+`PROJECT_CHECKS`: a check of the open project, for the Project screen's **Adapt to the editor** report (see [Bring an existing project](/docs/editor/editor/adapt-a-project)). `run(project)` resolves with suggestions: an `id` (stable, so a dismissed one stays dismissed), a `title`, a `detail` (what the editor can't do, why the change helps) and either a `fix` or an `action`. A fix computes its change without writing anything: `recordChanges` runs workspace operations on the files kept in memory, and the editor shows the result as a diff before applying it as one undo step.
+
+```ts
+import { PROJECT_CHECKS, recordChanges, workspaceIo } from '@nanoforge-dev/editor-sdk';
+
+context.contribute(PROJECT_CHECKS, {
+ id: 'counter.config',
+ run: async (project) => {
+ const io = workspaceIo(project);
+ if (io.exists('counter.json')) return [];
+ return [
+ {
+ id: 'counter.config',
+ title: 'Add a counter config',
+ detail: 'The Counter panel reads counter.json: without it, it starts at 0 every time.',
+ fix: {
+ title: 'Add counter.json',
+ changeset: () =>
+ recordChanges(io, 'Add counter.json', (memory) => memory.write('counter.json', '{ "start": 0 }\n')),
+ },
+ },
+ ];
+ },
+});
+```
+
+Checks run when a project opens, when a check is contributed, and after files change. Run the expensive parts in the code worker (an analyzer), never on the page.
+
+## Points of other plugins
+
+A plugin can define its own points with `defineExtensionPoint(id)`, and others contribute to them by declaring the same id. The ECS plugin has three:
+
+| Id | A value is |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `ecs.fieldEditors` | The inspector field of a value type, or of one referenced type. |
+| `ecs.paramPresets` | A visual preset that merges several constructor parameters into one control. |
+| `ecs.entityActions` | An action on an entity of the Hierarchy: `{ id, title, command, when }`. The command gets `{ app, entity, path }`; `when` sees `ecsEntity` and `ecsComponent:` (`ecsComponent:Position`). |
+| `ecs.sources` | What the ECS widgets edit for an app: a file and the function holding its spawns (`main`, or a method of a class), and read-only locations shown with it. The scene plugin uses it. |
+
+Declare `@nanoforge/ecs` in your manifest's `dependencies` to contribute to them.
+
+## Reading a point
+
+```ts
+const items = context.contributions(FILE_TEMPLATES); // observable of contributions
+items.subscribe((list) => console.log(list.map(({ value }) => value.id)));
+```
diff --git a/docs/editor/plugins/history.mdx b/docs/editor/plugins/history.mdx
new file mode 100644
index 0000000..751444f
--- /dev/null
+++ b/docs/editor/plugins/history.mdx
@@ -0,0 +1,98 @@
+---
+title: 'History'
+icon: 'history'
+description: 'Make what your plugin does undoable'
+---
+
+Undo in the editor is not one global list. Each area has its own **history context**: each file, the layout, the Files panel, and any context a plugin registers. `Ctrl+Z` acts on the context of what has focus, and the History panel shows them all.
+
+## A command
+
+A step is a `HistoryCommand`: a label and two functions.
+
+```ts
+const add = (step: number) => ({
+ label: `Add ${step}`,
+ do: () => count.set(count.get() + step),
+ undo: () => count.set(count.get() - step),
+});
+```
+
+`do` and `undo` may be async. Other fields: `mergeKey` (commands with the same key pushed close together become one step, for a drag or a slider), `preview` (what changed, for the History panel).
+
+## A context of your own
+
+```ts
+import { HistoryServiceToken } from '@nanoforge-dev/editor-sdk';
+
+const history = context.services
+ .get(HistoryServiceToken)
+ .registerContext({ id: 'counter', label: 'Counter', owner: context.name });
+context.subscriptions.add(history);
+
+await history.stack.push(add(1)); // runs do(), then records the step
+await history.stack.undo();
+await history.stack.redo();
+```
+
+`push` **runs** the command: do not apply the change yourself first.
+
+### Several changes, one step
+
+```ts
+await history.stack.transaction('Add twice', async (tx) => {
+ await tx.push(add(1));
+ await tx.push(add(1));
+});
+```
+
+If the function throws, the steps already done are undone. `compositeCommand` builds one command from several when you have them up front.
+
+## Point undo at your context
+
+`Ctrl+Z` needs to know which context your panel uses.
+
+```svelte
+
+```
+
+Or, when the panel always uses the same context, `"historyContext": "counter"` on the widget in the manifest.
+
+While a text field has focus, `Ctrl+Z` stays the field's own undo.
+
+## Changing files
+
+Do not write to files directly when the change should be undoable: edit them through the document service. The step then lands in the **file's** history (`file:`), next to what the user typed, and works whether the file is open in the code editor or not.
+
+```ts
+import { DocumentServiceToken } from '@nanoforge-dev/editor-sdk';
+
+const documents = context.services.get(DocumentServiceToken);
+await documents.edit('apps/client/src/main.ts', [{ start: 0, end: 0, text: '// hello\n' }], {
+ label: 'Add a greeting',
+});
+```
+
+An edit is a list of `{ start, end, text }` offsets in the file's current text. A step whose file changed underneath it (the content it produced is gone) is dropped rather than applied to the wrong text.
+
+To change code by its meaning rather than by offsets, see [code and code generation](/docs/editor/plugins/code-and-codegen).
+
+## A change across several files
+
+Take the commands instead of pushing them, and group them in a context of your own:
+
+```ts
+const commands = [
+ documents.editCommand('a.ts', editsA, { label: 'Move Health' }),
+ documents.editCommand('b.ts', editsB, { label: 'Move Health' }),
+];
+await history.stack.push(compositeCommand('Move Health', commands));
+```
+
+One undo then reverts both files.
diff --git a/docs/editor/plugins/manifest.mdx b/docs/editor/plugins/manifest.mdx
new file mode 100644
index 0000000..b8738fb
--- /dev/null
+++ b/docs/editor/plugins/manifest.mdx
@@ -0,0 +1,231 @@
+---
+title: 'Manifest reference'
+icon: 'file-code'
+description: 'Every field of a plugin nanoforge.manifest.json'
+---
+
+`nanoforge.manifest.json` sits at the root of the plugin's source folder. The build copies it into `dist/` and adds the `build` field. The JSON schema is `packages/kernel/schemas/plugin.schema.json` in the editor repository (`$schema` gives completion in most editors).
+
+## Identity
+
+| Field | Required | Description |
+| --------------------------------------- | -------- | --------------------------------------------------------------------------- |
+| `type` | yes | `"plugin"`. |
+| `name` | yes | `@scope/name`, lowercase letters, digits and `-`. The name in the registry. |
+| `version` | yes | Semver. |
+| `displayName` | | The name shown in the editor. |
+| `description` | | One sentence, shown in _Settings › Plugins_ and the marketplace. |
+| `keywords` | | Words the registry searches. A theme says `["theme"]`. |
+| `icon`, `tags`, `license`, `repository` | | Shown by the registry. |
+
+## Compatibility
+
+| Field | Description |
+| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `engines.editor` | **Required.** Semver range of editor versions the plugin runs on. Outside it, the plugin is listed as "needs another editor version" and not loaded. |
+| `dependencies` | Other plugins it needs: `["@scope/name"]` or `{ "@scope/name": "^1.0.0" }`. They activate first. A missing one stops the plugin. |
+| `optionalDependencies` | Plugins it uses when they are there. |
+| `engineLibs.required` | Engine libraries an app must have for the plugin to apply to it: `{ "@nanoforge-dev/ecs": "*" }`. See [engine libraries](/docs/editor/plugins/engine-libs). |
+| `engineLibs.optional` | Engine libraries it can use. |
+| `build` | Written by the build: the versions of Svelte and of the SDK it was compiled against. The editor refuses a plugin built for an incompatible runtime. |
+
+## Entries
+
+Paths relative to the built folder. A plugin that only contributes from its manifest (a theme, icons) has no `entry`. Any other key is refused: a typo (`clinet`) keeps the plugin from loading, and the error names the key.
+
+| Field | Runs in | Used for |
+| -------------- | ------------------- | ------------------------------------------------------------------------------------------------------- |
+| `entry.client` | the editor's page | Panels, commands, everything visible. |
+| `entry.worker` | the code worker | Reading and transforming the game's code. See [code and code generation](/docs/editor/plugins/code-and-codegen). |
+| `entry.server` | the editor's server | Code that needs the machine: files outside the project, processes. See [the SDK](/docs/editor/plugins/sdk#server-entries). |
+
+## Activation
+
+`activation` lists the events that load the plugin's code. Default: `["onStartup"]`.
+
+| Event | Fires when |
+| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
+| `onStartup` | the editor starts |
+| `onWidget:` | a panel or screen with that id is first shown |
+| `onCommand:` | that command runs |
+| `onScreen:`, `onProjectType:`, `onLanguage:`, `onUri:` | accepted by the schema, but the editor does not fire them yet. A screen is a widget: use `onWidget`. |
+
+Prefer `onWidget` and `onCommand`: a plugin loaded at startup delays the others.
+
+## Contributions
+
+Everything under `contributes` is applied when the manifest is read, before the plugin's code loads.
+
+### `commands`
+
+```json
+{
+ "id": "counter.add",
+ "title": "Add to the counter",
+ "category": "Counter",
+ "when": "runtime.active",
+ "palette": true
+}
+```
+
+| Field | Description |
+| ---------- | -------------------------------------------------------------------------------------- |
+| `id` | **Required.** Prefix it with your plugin's short name. |
+| `title` | **Required.** Sentence case, says what it does. A trailing `…` when it opens a dialog. |
+| `category` | Shown before the title in the palette: `Counter: Add to the counter`. |
+| `icon` | An icon name. |
+| `when` | A [when clause](#when-clauses): the command is offered only while it is true. |
+| `palette` | `false` hides it from the command palette (a command that needs arguments). |
+
+The code registers the handler with `context.registerCommand(id, handler)`.
+
+### `widgets`
+
+Panels (docks) and screens.
+
+| Field | Default | Description |
+| ---------------- | ------- | -------------------------------------------------------------------------------------- |
+| `id` | | **Required.** |
+| `title` | | **Required.** The tab's name. |
+| `icon` | | An icon name (`folder-tree`): a dock shows only the icon in its stripe. |
+| `kind` | `dock` | `dock`: a panel in a dock or a floating window. `screen`: a main screen in the center. |
+| `description` | | Screens: one line on what it is for, shown in the screen tab's tooltip. |
+| `defaultSlot` | | `leftTop`, `leftBottom`, `rightTop`, `rightBottom`, `bottom` or `bottomRight`. |
+| `order` | `0` | Order among the tabs of the slot, or among screens. |
+| `openByDefault` | `true` | Whether the default layout shows it. |
+| `essential` | `false` | Whether the simple layout shows it too (the few panels most work needs). |
+| `singleton` | `true` | One instance at a time. |
+| `when` | | Offered in menus only while true. |
+| `historyContext` | | The history that undo and redo act on while the widget has focus. |
+| `tip` | | Docks: `{ text, docs? }`, a hint shown above the panel until the user puts it away; `docs` is a page of the documentation (`editor/entities`). |
+
+The code gives the widget its view with the `WIDGET_VIEWS` extension point. See [widgets and styles](/docs/editor/plugins/widgets-and-styles).
+
+### `menus`
+
+```json
+{ "menu": "edit", "command": "counter.add", "group": "counter", "order": 0 }
+```
+
+| Field | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `menu` | **Required.** A menu of the menu bar (`file`, `edit`, `view`, `run`, `help`, `vcs`, or one a plugin added with `MENU_BAR`), a submenu id, or a context menu id. |
+| `command` | The command to run. The entry shows the command's title and shortcut. |
+| `submenu`, `title` | Instead of a command: opens the submenu with that id. |
+| `group` | Entries are separated by group (default `main`), then sorted by `order`. |
+| `when` | Shown only while true. |
+| `args` | Arguments passed to the command. |
+
+### `keybindings`
+
+```json
+{ "key": "Mod+Alt+K", "command": "counter.add", "when": "!textInputFocus" }
+```
+
+- Write `Mod` for Ctrl (Cmd on macOS). Two strokes separated by a space make a chord: `Mod+K Mod+S`. A modifier twice is a double tap: `Shift Shift`.
+- These are **defaults**: users change them in _Settings › Keyboard shortcuts_.
+- Don't bind a single stroke that starts an existing chord, and don't give a default shortcut to an action that publishes or deletes.
+
+### `keymapPresets`
+
+A named set of shortcuts users can choose in _Settings › Keyboard shortcuts_.
+
+```json
+{ "id": "hello", "title": "Hello keys", "bindings": [{ "key": "F9", "command": "hello.twice" }] }
+```
+
+A binding with `"remove": true` cancels a default shortcut.
+
+### `settings`
+
+```json
+{ "key": "step", "type": "number", "default": 1, "title": "Step", "category": "Counter" }
+```
+
+The key is prefixed with the plugin's name: `@acme/counter.step`. See [settings](/docs/editor/plugins/settings) for types and scopes.
+
+### `themes`
+
+A color theme: `id`, `label`, and either `extends` (another theme's id) with the colors it changes, or `kind` (`dark` or `light`) with every color. Also `syntax` (code colors) and `tokens` (fonts and corners). See [make a theme](/docs/editor/plugins/themes).
+
+### `icons`, `iconThemes`
+
+Icons as SVG files of the plugin, by name, and icon themes that replace the editor's icons and give file and folder icons. See [make a theme](/docs/editor/plugins/themes#icons).
+
+### `tours`
+
+A guided tour: steps shown one at a time over the editor, each pointing at a control found by its role and accessible name (the way tests find it), optionally inside a panel.
+
+```json
+{
+ "id": "counter.tour",
+ "title": "The counter",
+ "steps": [
+ {
+ "id": "panel",
+ "title": "The counter",
+ "text": "Show the Counter panel.",
+ "action": { "title": "Show it", "command": "workbench.openWidget", "args": ["counter.panel"] },
+ "target": { "role": "region", "name": "Counter" }
+ },
+ {
+ "id": "add",
+ "title": "Count",
+ "text": "Click Add one.",
+ "target": { "role": "button", "name": "Add one", "within": { "role": "region", "name": "Counter" } },
+ "advanceWhenChanged": "counter.value"
+ }
+ ]
+}
+```
+
+A step shows only while its `when` holds, and goes on by itself once `advanceWhen` holds or the key of `advanceWhenChanged` changes. `"exact": false` on a target matches a name that only starts with `name` (a tree row says more than its label). The command `tour.start` with the tour's id starts it.
+
+### `documentEditors`
+
+Opens files matching a glob with one of your widgets instead of the code editor.
+
+```json
+{
+ "pattern": "**/*.scene.json",
+ "widget": "scenes.editor",
+ "command": "scenes.open",
+ "title": "Scene editor",
+ "priority": 10
+}
+```
+
+### `itemOwner`
+
+For plugins that describe items of the game's code (components, systems…): `schema` (the version of the data it writes) and `tags` (the TSDoc tags it owns). See [code and code generation](/docs/editor/plugins/code-and-codegen#item-owners).
+
+## When clauses
+
+A `when` is an expression over **context keys**.
+
+```text
+runtime.active && !textInputFocus
+fileExtname == .ts || fileExtname == .js
+!(fileReadOnly) && fileSelectionCount == 1
+codeEditor.activeFile =~ /\.component\.ts$/
+```
+
+Operators: `!`, `&&`, `||`, `==`, `!=`, `=~` (regular expression), `in`, and parentheses. A bare word on the right of `==` is a string.
+
+| Key | Value |
+| --------------------------------------------------------------- | -------------------------------------------------------- |
+| `textInputFocus` | true while a text field has focus |
+| `focusedWidget` | id of the focused widget |
+| `historyContext` | id of the history undo would act on |
+| `activeApp` | id of the app the user works on |
+| `engineLib:` | true when the active app has that engine library |
+| `runtime.active`, `runtime.state`, `runtime.controllable` | the game is playing, its state, whether it can be paused |
+| `codeEditor.activeFile` | path of the file in the focused code editor |
+| `git.repository`, `git.head` | the project is a Git repository, its current commit |
+| `screen` | id of the screen shown |
+| `editor.local` | a local editor (games, Git, installs) |
+| `ecs.entityCount`, `ecs.revision` | entities of the edited code, a count bumped on each edit |
+| `problems.hasErrors` | the project's code has errors (unset until first checked) |
+| `fileKind`, `fileExtname`, `fileReadOnly`, `fileSelectionCount` | in file context menus |
+
+A plugin sets its own keys with `context.contextKeys.set(key, value)`.
diff --git a/docs/editor/plugins/overview.mdx b/docs/editor/plugins/overview.mdx
new file mode 100644
index 0000000..357586f
--- /dev/null
+++ b/docs/editor/plugins/overview.mdx
@@ -0,0 +1,66 @@
+---
+title: 'Plugins overview'
+icon: 'plug'
+description: 'What an editor plugin is, where it lives and how the editor loads it'
+---
+
+Almost everything in the NanoForge editor is a plugin: the file manager, the code editor, the Game and Scene screens, the ECS panels, the console, Git. Your own plugins use the same API as these.
+
+A plugin is a folder with:
+
+- `nanoforge.manifest.json`: its name, what it adds to the editor, and when to load it;
+- a **client entry** (`index.js`): code that runs in the editor's page;
+- optionally a **worker entry** (code analysis and code generation) and a **server entry** (code that runs in the editor's server);
+- its styles and assets.
+
+## Where plugins live
+
+The editor looks in four places. When the same plugin is in several, the later one in this table is used.
+
+| Source | Folder | Loaded |
+| --------- | -------------------------------------------------- | --------------------------------- |
+| Built in | shipped with the editor | always |
+| Installed | `~/.nanoforge/editor/plugins/@scope/name` | in every project |
+| Project | `/.nanoforge/plugins/@scope/name` | while that project is open |
+| Dev | the folders listed in `DEV_PLUGINS` (their `dist`) | always, and reloaded when rebuilt |
+
+_Settings › Plugins_ lists every plugin with its source and state, lets you turn one off, and installs plugins from the marketplace.
+
+A project plugin's server entry only runs in a local editor, never in a hosted one.
+
+The editor's page has a Content Security Policy: in a hosted editor, the page (plugins included) connects to the editor's own origin only; in a local editor, the page, plugins and games, may connect anywhere (`http:`, `https:`, `ws:`, `wss:`).
+
+## How a plugin is loaded
+
+1. The editor reads every manifest. Everything a manifest declares in `contributes` (commands, menus, panels, settings, shortcuts) is in place **before any plugin code runs**.
+2. A plugin's code is fetched and `activate` is called when one of its **activation events** happens: a panel of the plugin is shown, one of its commands runs, or at startup.
+3. When the plugin is turned off or replaced, everything it added through `context.subscriptions` is removed.
+
+So a plugin that only shows a panel costs nothing until the panel is opened.
+
+## What a plugin can import
+
+Only the SDK:
+
+- `@nanoforge-dev/editor-sdk`: services, commands, settings, history, code, runtime;
+- `@nanoforge-dev/editor-sdk/ui`: panels, menus, the status bar, and the editor's own components;
+- `@nanoforge-dev/editor-sdk/worker`: types for worker entries.
+
+The editor provides these modules, and Svelte, at run time: they are not bundled into your plugin, so your panels use the editor's own components and theme. Plugins are written in **Svelte 5 with runes**.
+
+## Next
+
+
+
+ `nf create plugin`, run it in the editor, change it.
+
+
+ Every field of `nanoforge.manifest.json`.
+
+
+ The activation context and the editor's services.
+
+
+ Every place a plugin can add something.
+
+
diff --git a/docs/editor/plugins/sdk.mdx b/docs/editor/plugins/sdk.mdx
new file mode 100644
index 0000000..2934f05
--- /dev/null
+++ b/docs/editor/plugins/sdk.mdx
@@ -0,0 +1,197 @@
+---
+title: 'SDK'
+icon: 'code'
+description: 'The activation context and the services of the editor'
+---
+
+A plugin imports the SDK and nothing else from the editor.
+
+| Module | Holds |
+| ---------------------------------- | -------------------------------------------------------------------------- |
+| `@nanoforge-dev/editor-sdk` | The plugin entry, services, observables, settings, history, code, runtime. |
+| `@nanoforge-dev/editor-sdk/ui` | Extension points of the workbench, UI services, and the component kit. |
+| `@nanoforge-dev/editor-sdk/worker` | `defineWorkerPlugin` and the types of worker entries. |
+
+## The plugin entry
+
+```ts
+import { definePlugin } from '@nanoforge-dev/editor-sdk';
+
+export default definePlugin({
+ activate(context) {
+ // add things to the editor
+ },
+ deactivate() {
+ // optional: the editor already disposes context.subscriptions
+ },
+});
+```
+
+`activate` may be `async`. The editor waits for it before running the command or showing the panel that activated the plugin.
+
+## The context
+
+| Member | Use |
+| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
+| `name`, `manifest`, `source` | The plugin's name, its manifest, where it was loaded from. |
+| `subscriptions` | A store of disposables, disposed when the plugin stops. **Add everything you register.** |
+| `services` | `services.get(Token)` gives a service; `tryGet` gives `undefined` when it is not there. |
+| `registerCommand(id, handler)` | The handler of a command declared in the manifest. Its first argument is the services. |
+| `executeCommand(id, ...args)` | Runs any command (it activates the plugin that owns it). |
+| `contribute(point, value)` | Adds a value to an [extension point](/docs/editor/plugins/extension-points). |
+| `contributions(point)` | An observable of what an extension point holds. |
+| `contextKeys` | Sets and reads keys used in `when` clauses. |
+| `logger` | `debug`, `info`, `warn`, `error`. Lines show in the Console under _Plugins_, with your plugin's name. |
+| `t(key, params)`, `registerMessages(locale, messages)` | Translations of the plugin. |
+| `resolveAsset(path)` | URL of a file of the plugin's built folder. |
+| `eligibleApps` | An observable of the project's apps that have the engine libraries the plugin requires. |
+| `provide(token, value)` | Offers a service to the editor and to other plugins. |
+| `override(token, decorate)` | Wraps a service of the editor. |
+| `scope` | A container private to the plugin. |
+
+Everything that registers something returns a **disposable**. Pass it to `context.subscriptions.add(...)`.
+
+## Services
+
+```ts
+import { EditorServices, ProjectServiceToken } from '@nanoforge-dev/editor-sdk';
+
+const commands = context.services.get(EditorServices.Commands);
+const project = context.services.get(ProjectServiceToken).current.get();
+```
+
+| Token | Service |
+| ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
+| `EditorServices.Commands` | The command registry: `execute(id, ...args)`. |
+| `EditorServices.ContextKeys` | Context keys of `when` clauses. |
+| `EditorServices.EventBus` | Events between plugins. |
+| `EditorServices.Extensions` | The extension registry (`getValues(point)`). |
+| `EditorServices.Localization`, `EditorServices.Logger`, `EditorServices.EngineLibs` | Translations, loggers, engine libraries of apps. |
+| `ProjectServiceToken` | The open project: `current` (an observable), with its `model` (apps, engine libraries) and its `fs` (files, change events). |
+| `SettingsServiceToken`, `SettingsRegistryToken` | [Settings](/docs/editor/plugins/settings). |
+| `HistoryServiceToken` | [History](/docs/editor/plugins/history): undo and redo. |
+| `DocumentServiceToken` | Text of files, open or not, and edits that can be undone. |
+| `CodeServiceToken`, `CatalogServiceToken`, `DiagnosticsServiceToken` | [Code](/docs/editor/plugins/code-and-codegen): analysis, items, problems. |
+| `RuntimeServiceToken` | The running game: play, pause, stop, and its events. See [engine libraries](/docs/editor/plugins/engine-libs). |
+| `RpcClientToken` | Calls to the editor's server. |
+| `PluginHostToken` | The plugins and their state. |
+| `AccountSyncToken` | State of the account settings sync. |
+
+From `@nanoforge-dev/editor-sdk/ui`:
+
+| Token | Service |
+| ------------------------------------------------ | ----------------------------------------------------------- |
+| `NotificationServiceToken` | `notify(severity, message, { detail, actions, timeout })`. |
+| `PromptServiceToken` | `ask(options)`: asks the user for a text in a small dialog. |
+| `StyleServiceToken` | Injects the plugin's CSS. |
+| `ThemeServiceToken` | The current theme and the list of themes. |
+| `WorkbenchServiceToken`, `LayoutControllerToken` | Widgets and the layout. |
+| `KeybindingServiceToken` | The resolved shortcuts. |
+
+## Observables
+
+Values that change are `Observable`s: `get()` reads, `subscribe(listener)` listens and returns an unsubscribe function. In Svelte, read one as a store with `$`.
+
+```ts
+import { ObservableValue, derived, observe } from '@nanoforge-dev/editor-sdk';
+
+const count = new ObservableValue(0);
+const label = derived([count], (value) => `${value} clicks`);
+context.subscriptions.add(observe(label, (text) => context.logger.info(text)));
+count.set(1);
+```
+
+`observe` calls the listener at once and on every change, and returns a disposable.
+
+## Disposables and events
+
+- `DisposableStore`: holds disposables and disposes them together. `context.subscriptions` is one.
+- `toDisposable(fn)`: makes a disposable of a function.
+- `Emitter`: an event source. `emitter.event(listener)` subscribes and returns a disposable; `emitter.fire(value)` notifies.
+
+## Calling the editor's server
+
+The server speaks typed **contracts**. The SDK exports those a plugin may need.
+
+```ts
+import {
+ GitContract,
+ RegistryContract,
+ RpcClientToken,
+ SessionContract,
+} from '@nanoforge-dev/editor-sdk';
+
+const rpc = context.services.get(RpcClientToken);
+const session = await rpc.api(SessionContract).info(null); // mode, user, features
+const status = await rpc.api(GitContract).status({ project: project.id });
+```
+
+Errors are `RpcError`s with a `code` (`NOT_FOUND`, `FORBIDDEN`, `UNAVAILABLE`…). A hosted editor refuses with `FORBIDDEN` what only a local editor can do.
+
+## Server entries
+
+A plugin with `entry.server` runs code in the editor's server (Bun), for what a browser cannot do. It implements a **contract** in its own namespace, `plugin.`, which its client entry then calls.
+
+```ts
+// index.ts (client): the contract, and the call
+import { z } from 'zod';
+
+import { RpcClientToken, defineContract } from '@nanoforge-dev/editor-sdk';
+
+export const EchoContract = defineContract('plugin.@acme/echo', {
+ methods: { echo: { input: z.object({ text: z.string() }), output: z.string() } },
+});
+
+const answer = await context.services.get(RpcClientToken).api(EchoContract).echo({ text: 'hi' });
+```
+
+```js
+// server.js: a file of its own, not built with the client entry
+import { z } from 'zod';
+
+// The same contract, written out: the SDK does not exist in the server.
+const EchoContract = {
+ namespace: 'plugin.@acme/echo',
+ methods: { echo: { input: z.object({ text: z.string() }), output: z.string() } },
+ events: {},
+};
+
+export const activate = (context) => {
+ context.implement(EchoContract, {
+ methods: { echo: ({ text }) => `${text} from ${process.platform}` },
+ });
+};
+```
+
+The server context has `name`, `manifest`, `subscriptions`, `logger`, `namespace` and `implement(contract, implementation)`. Inputs and outputs are checked against the contract's schemas.
+
+
+ Server entries are less finished than the rest. The plugin build does not handle them: a server
+ entry must **not import the SDK** (those imports only work in the editor's page), and must
+ **bundle what it imports** (`zod` here) or be built apart with a bundler targeting Bun, then
+ shipped in the plugin's folder.
+
+
+A server entry runs with the rights of the editor's server. It starts when the plugin is installed and stops when it is uninstalled. A project plugin's server entry never runs in a hosted editor.
+
+## Dialogs
+
+Mount a Svelte component from a command, and unmount it when it closes. The kit's `Dialog` handles focus and the overlay.
+
+```ts
+import { mount, unmount } from 'svelte';
+
+context.registerCommand('counter.about', () => {
+ const target = document.createElement('div');
+ document.body.append(target);
+ const dialog = mount(AboutDialog, {
+ target,
+ props: {
+ onclose: () => {
+ void unmount(dialog);
+ target.remove();
+ },
+ },
+ });
+});
+```
diff --git a/docs/editor/plugins/settings.mdx b/docs/editor/plugins/settings.mdx
new file mode 100644
index 0000000..d399b23
--- /dev/null
+++ b/docs/editor/plugins/settings.mdx
@@ -0,0 +1,127 @@
+---
+title: 'Settings'
+icon: 'sliders-horizontal'
+description: 'Declare settings, read them, and choose where they are saved'
+---
+
+A plugin's settings show in the Settings dialog with the others, are searchable, and are saved in the scope the user chooses.
+
+## Declare in the manifest
+
+```json
+"settings": [
+ {
+ "key": "step",
+ "type": "number",
+ "integer": true,
+ "minimum": 1,
+ "default": 1,
+ "title": "Step",
+ "description": "How much each click adds.",
+ "category": "Counter"
+ }
+]
+```
+
+The key is prefixed with the plugin's name: this one is `@acme/counter.step`.
+
+| Field | Description |
+| ---------------------- | ------------------------------------------------------------------------------------------ |
+| `key` | **Required.** Letters, digits and dots. |
+| `type` | **Required.** See the types below. |
+| `default` | **Required.** Must fit the type. |
+| `title`, `description` | Shown in the dialog. The search looks in both. |
+| `category` | Where it is listed: `Counter`, or `Editor/Game view` for a sub-category. |
+| `order`, `tags` | Order in the category; extra search words. |
+| `scopes` | The scopes it can be saved in. Default: all. |
+| `sync` | `false`: never saved to the account. |
+| `mergeStrategy` | How scopes combine: `replace` (default), `deep` (objects merged), `union` (arrays joined). |
+| `deprecated` | A message; the setting leaves the dialog. |
+| `renamedFrom` | Former keys, whose saved values are still read. |
+
+### Types
+
+| `type` | Options | Editor |
+| --------- | ------------------------------------ | --------------------- |
+| `string` | `enum` (a list), `pattern` (a regex) | a text box, or a list |
+| `number` | `integer`, `minimum`, `maximum` | a number box |
+| `boolean` | | a switch |
+| `array` | `items` (a type) | edited as JSON |
+| `record` | `values` (a type) | edited as JSON |
+
+## Scopes
+
+A setting's value is the one of the highest scope that has it.
+
+| Scope | Saved | For |
+| -------------- | --------------------------------------------- | -------------------------------- |
+| default | in the definition | |
+| `account` | with the user's account | preferences that follow the user |
+| `machine` | in this browser | what depends on the machine |
+| `project` | `.nanoforge/editor/settings.json`, committed | what the whole team shares |
+| `projectLocal` | `.nanoforge/editor/local.json`, not committed | this user on this project |
+
+A project file cannot force a setting that does not allow the `project` scope: such values are ignored.
+
+## Read and follow
+
+```ts
+import { SettingsServiceToken, observe } from '@nanoforge-dev/editor-sdk';
+
+const settings = context.services.get(SettingsServiceToken);
+
+const step = settings.get('@acme/counter.step'); // the value now
+context.subscriptions.add(
+ observe(settings.observe('@acme/counter.step'), (value) => {
+ // called now and each time the value changes, whatever scope changed
+ }),
+);
+```
+
+`settings.inspect(key)` gives the value in each scope.
+
+## Write
+
+```ts
+await settings.set('@acme/counter.step', 5, 'machine');
+await settings.reset('@acme/counter.step', 'machine');
+```
+
+Writing validates the value, and fails for a scope the setting does not allow.
+
+## Declare in code
+
+For a setting whose type the manifest vocabulary cannot express, define it with a zod schema and register it:
+
+```ts
+import { z } from 'zod';
+
+import { SettingsRegistryToken, defineSetting } from '@nanoforge-dev/editor-sdk';
+
+const palette = defineSetting({
+ key: '@acme/counter.palette',
+ schema: z.array(z.string().regex(/^#[0-9a-f]{6}$/)).max(8),
+ default: [],
+ title: 'Palette',
+ category: 'Counter',
+ scopes: ['account', 'machine'],
+});
+context.subscriptions.add(context.services.get(SettingsRegistryToken).register(palette));
+```
+
+## A page of your own
+
+When a list of rows is not the right editor (the keyboard shortcuts page, for example), contribute a page to `SETTINGS_PAGES`. The page gets the dialog's pending changes: what it sets is saved when the user presses **Apply** or **OK**, like every other setting.
+
+```ts
+import { SETTINGS_PAGES } from '@nanoforge-dev/editor-sdk/ui';
+
+context.contribute(SETTINGS_PAGES, {
+ id: 'counter',
+ title: 'Counter',
+ settings: ['@acme/counter.palette'], // they leave the category list
+ component: PalettePage, // gets { services, page }
+});
+```
+
+In the page, `page.value(key)` reads a setting with its pending change, `page.set(key, value, scope)` changes it, and `page.revision` is an observable bumped on every change.
diff --git a/docs/editor/plugins/themes.mdx b/docs/editor/plugins/themes.mdx
new file mode 100644
index 0000000..b0bf3e8
--- /dev/null
+++ b/docs/editor/plugins/themes.mdx
@@ -0,0 +1,106 @@
+---
+title: 'Make a theme'
+icon: 'palette'
+description: 'Color themes, code colors, fonts and icons, from a manifest with no code'
+---
+
+A theme is a plugin with no code: everything is in its `nanoforge.manifest.json`. Start one with the CLI:
+
+```sh
+nf create plugin --name @acme/forest --template theme
+cd forest
+node build.mjs --watch # copies the manifest and icons to dist/ on every change
+DEV_PLUGINS=$(pwd) nf editor ../my-game # in another terminal
+```
+
+Choose it in _Settings › Editor › Appearance_. While `--watch` runs, each save of the manifest changes the editor at once. `tooling/example-theme` in the editor's repository is a complete example: a theme, an icon and an icon theme.
+
+## A theme
+
+```json
+{
+ "type": "plugin",
+ "name": "@acme/forest",
+ "version": "0.1.0",
+ "keywords": ["theme"],
+ "engines": { "editor": ">=0.1.0" },
+ "contributes": {
+ "themes": [
+ {
+ "id": "forest",
+ "label": "Forest",
+ "extends": "nanoforge-dark",
+ "colors": { "accent": "#2f7d6d", "accent-hover": "#286a5d", "accent-text": "#7fd6c2" },
+ "syntax": { "keyword": "#7fd6c2", "string": "#e6c07b" },
+ "tokens": { "radius-control": "4px" }
+ }
+ ]
+ }
+}
+```
+
+- `id`: unique among installed themes. The built-in `nanoforge-dark` and `nanoforge-light` can't be replaced: a theme whose id is already taken is left out, and named in the Console.
+- `extends`: the theme it starts from, `nanoforge-dark`, `nanoforge-light` or another plugin's theme. Give only what changes. A theme that extends none gives `kind` (`dark` or `light`) and every color.
+- No `entry`: a theme has no code.
+- `keywords: ["theme"]` lists it under _Get more themes_ once it is in the registry.
+
+A color is any CSS color: `#rrggbb`, `rgb()`, `oklch()`. A value never holds `;`, `{`, `}`, `\`, `<`, `>`, `@`, `/*`, `url()` or an image, and closes its brackets and quotes: a theme brings no files but its icons. A `var()` works in the editor's own UI, but the code editor and the contrast check can't read it: give the code editor's colors (`surface`, `raised`, `text`, `accent`, `selection`…) as plain colors, or it keeps its own for them. An unknown token is refused, by name, in the Console (`Invalid contributes.themes of "@acme/forest"`).
+
+### Colors
+
+| Token | For |
+| ---------------------------------------------- | ---------------------------------------------------- |
+| `bg`, `surface`, `raised`, `sunken` | Behind panels, panels, menus and dialogs, inputs |
+| `hover`, `pressed` | Rows and buttons under the pointer, pressed |
+| `border`, `border-strong` | Lines, edges of controls |
+| `text`, `text-muted`, `text-faint` | Text, from the most to the least important |
+| `accent`, `accent-hover`, `on-accent` | Primary buttons and their text |
+| `accent-text` | The accent used as text (links, active markers) |
+| `focus`, `selection`, `selection-text` | Keyboard focus, selected rows and text |
+| `danger`, `warning`, `success` | Status |
+| `scrim` | Behind dialogs |
+
+### Code colors (`syntax`)
+
+`keyword`, `string`, `number`, `comment`, `type`, `variable`, `regexp`, `delimiter`. Those you leave out keep the code editor's own.
+
+### Tokens
+
+`font-ui`, `font-code`, `radius-control`, `radius-float`. A font must be one the computer has, or a web font loaded another way: the editor loads only its own.
+
+The _Density_ setting (compact, normal, comfortable) is the user's, not the theme's.
+
+## Contrast
+
+When a theme is applied, the editor checks it as WCAG does: the three text colors need 4.5:1 on each background (`bg`, `surface`, `raised`, `sunken`), `border-strong` 3:1, `on-accent` 4.5:1 on `accent`, and `selection-text` on `selection`. What falls under is named once in the Console:
+
+```text
+Theme "forest" of @acme/forest has text too faint to read (WCAG AA): on-accent on accent is 4.29:1 (needs 4.5:1).
+```
+
+## Icons
+
+`contributes.icons` adds icons by name, as SVG files of the plugin. Panels, menus and file icons use them by their name.
+
+```json
+"icons": [{ "id": "forest-leaf", "path": "icons/leaf.svg" }]
+```
+
+An icon theme replaces the editor's icons while it is chosen (_Settings › Editor › Appearance › Icons_). Its id is unique too: the built-in `nanoforge` can't be replaced.
+
+```json
+"iconThemes": [
+ {
+ "id": "forest-icons",
+ "label": "Forest icons",
+ "icons": { "folder": "icons/folder.svg", "folder-open": "icons/folder-open.svg", "forest-code": "icons/code.svg" },
+ "files": [{ "pattern": "**/*.{ts,js}", "icon": "forest-code" }],
+ "folders": [{ "pattern": "**/assets", "icon": "folder", "iconOpen": "folder-open" }]
+ }
+]
+```
+
+- `icons`: any icon of the editor by its name (`folder`, `play`, `settings`, the panels' icons…), or new names for `files` and `folders`.
+- `files` and `folders`: patterns of the Files panel, ahead of every other plugin's while the icon theme is chosen.
+- A path is a relative `.svg` file inside the plugin: never `..`, an absolute path or another site.
+- An SVG is drawn in the color of the text around it (a CSS mask): draw it in one color, its shape only. It is never put in the page, so it can't run scripts.
diff --git a/docs/editor/plugins/widgets-and-styles.mdx b/docs/editor/plugins/widgets-and-styles.mdx
new file mode 100644
index 0000000..ac18d56
--- /dev/null
+++ b/docs/editor/plugins/widgets-and-styles.mdx
@@ -0,0 +1,110 @@
+---
+title: 'Widgets and styles'
+icon: 'layout-panel-left'
+description: 'Panels, screens, their state, and how to style them like the editor'
+---
+
+A **widget** is a panel in a dock (or a floating window), or a **screen** in the center. The manifest declares it; the code gives it a view.
+
+## Declare and show
+
+```json
+"widgets": [
+ { "id": "counter.panel", "title": "Counter", "icon": "plus", "defaultSlot": "rightBottom" }
+]
+```
+
+```ts
+import { WIDGET_VIEWS, type WidgetInstance } from '@nanoforge-dev/editor-sdk/ui';
+
+context.subscriptions.add(
+ context.contribute(WIDGET_VIEWS, {
+ id: 'counter.panel',
+ component: Panel as Component<{ instance: WidgetInstance }>,
+ }),
+);
+```
+
+With `"activation": ["onWidget:counter.panel"]`, the plugin loads when the panel is first shown. Users move panels between docks, float them and close them; _View › Panels_ lists them all.
+
+## The widget instance
+
+The component gets `instance`:
+
+| Member | Use |
+| ------------------------------- | ------------------------------------------------------------------------------------ |
+| `services` | The editor's services. |
+| `visible` | An observable: true while the widget is on screen. |
+| `onShow`, `onHide` | Events of the same. |
+| `getState()`, `setState(state)` | A small JSON state (scroll, filters, expanded nodes) kept across reloads. |
+| `setHistoryContext(id)` | Which history `Ctrl+Z` acts on while the widget has focus. See [history](/docs/editor/plugins/history). |
+
+
+ A tab that was shown once stays mounted while hidden. Do expensive work, and ask the running game
+ for data, only while `instance.visible` is true.
+
+
+## Svelte rules
+
+- Plugins compile in **runes mode** (`$props`, `$state`, `$derived`, `$effect`).
+- A value that changes outside Svelte must be an observable (read with `$`), or state you update from a subscription.
+- A store that hands back the same array or object does not update the view: return a new one.
+
+## The component kit
+
+Use the editor's components so your panel looks and behaves like the rest: `Button`, `IconButton`, `Input`, `NumberInput`, `Checkbox`, `Switch`, `Select`, `Combobox`, `Tabs`, `Tree`, `Menu`, `ContextMenu`, `Dialog`, `Tooltip`, `EmptyState`, `Icon`, `Splitter`, `PropertyGrid`, `ColorPicker`, `Vector2Input`.
+
+```svelte
+
+
+
+
+```
+
+- Give every control an accessible name (`aria-label` when there is no visible label).
+- Write labels in sentence case, with a verb that says what the button does.
+- Icons are Lucide names. A plugin adds its own with `registerIcons({ name: Component })`. A dock panel shows only its icon, in a stripe on the edge of the window, before its plugin activates: until then, an icon the plugin registers shows as a box. Prefer an `onStartup` registration, or an icon the editor already has.
+
+## Styles
+
+Component `