# Configuration Reference

Everything about a DiscoVR experience is configured through the attributes of a single `<discovr>` tag — see [Getting Started](getting-started.md) if you haven't added one yet.

## Value format

Every attribute value is read as plain text, including booleans and numbers: write `"true"` / `"false"` literally, and numbers as plain digits (e.g. `posX:2`). There is no type coercion on DiscoVR's side beyond what each feature does internally.

Attributes come in two shapes:
- **Simple attributes** map directly to one setting, e.g. `<discovr debug="true">`.
- **Grouped attributes** pack several related settings into one attribute, as a `;`-separated list of `key:value` pairs, e.g. `<discovr network="enable:true;showChat:true">`.

## Simple attributes

| Attribute | Default | Description |
|---|---|---|
| `debug` | `false` | Logs the resolved configuration object to the console once it's been read from the tag. |
| `physics` | `false` | Enables the PhysX physics engine and, when `presets="defaultContents:true"`, adds physics-driven demo objects. |
| `speech` | `false` | Enables the speech engine component (`i-speechengine`) on the scene. |
| `modular` | `true` | Loads A-Frame as a native ES module (recommended). Set to `false` only if you need A-Frame loaded as a classic script instead. |
| `externalContent` | *(none)* | URL (or path relative to the DiscoVR host) of an HTML fragment to fetch and inject into the scene as a container entity. |
| `externalAssets` | *(none)* | URL (or relative path) of an HTML fragment to fetch and inject into `<a-assets>`. |
| `externalScripts` | *(none)* | Comma-separated list of extra classic `<script>` URLs (or relative paths) to load. |
| `externalModules` | *(none)* | Comma-separated list of extra ES module URLs (or relative paths) to load. |
| `externalStyles` | *(none)* | Comma-separated list of extra stylesheet URLs (or relative paths) to load. |

## Grouped attributes

### `presets`

Scene-level setup: the base `<a-scene>` attributes (background, renderer, shadows, raycaster/cursor, fog, reflection), plus optional demo content.

| Key | Default | Description |
|---|---|---|
| `defaultScene` | `false` | Set to `true` to use DiscoVR's built-in demo scene setup instead of the `scene*` keys below (white background, ACESFilmic tone mapping, PCF shadows) — useful while getting started, not something a real experience typically wants. |
| `defaultLights` | `false` | Adds a default ambient + directional light. |
| `defaultContents` | `false` | Adds demo objects (a prototype cube, an interactive box, and — if `physics="true"` — a small physics playground). Requires `defaultScene:true` for the objects themselves to appear. |

**Whenever `defaultScene` is *not* `true`** (the normal case for a real experience), the scene's attributes are instead built from these keys — so you always get a fully configured scene, without needing `defaultScene:true`:

| Key | Default | Description |
|---|---|---|
| `sceneID` | `mainscene` | The `id` attribute of `<a-scene>`. |
| `sceneBackground` | `#000000` | Scene background color. |
| `sceneRendererToneMapping` | `no` | A-Frame renderer `toneMapping` (`no`, `Linear`, `Reinhard`, `Cineon`, `ACESFilmic`). |
| `sceneRendererToneMappingExposure` | `1` | Exposure used by the tone mapping. |
| `sceneRendererAntialias` | `auto` | Renderer `antialias` (`true` / `false` / `auto`). |
| `sceneRendererExtraParameters` | *(empty)* | Raw text appended as-is to the `renderer` attribute, for any renderer sub-property not covered above (e.g. `colorManagement: true;`). |
| `sceneShadowType` | `pcf` | Scene `shadow` component type (`pcf`, `basic`, `pcfsoft`, `vsm`). |
| `sceneShadowExtraParameters` | *(empty)* | Raw text appended as-is to the `shadow` attribute. |
| `sceneRaycasterObjects` | `.raycastable` | Selector for objects the default raycaster/cursor can hit. |
| `sceneRaycasterExtraParameters` | *(empty)* | Raw text appended as-is to the `raycaster` attribute. |
| `sceneCursorRayOrigin` | `mouse` | Cursor component `rayOrigin` (`mouse` or `entity`). |
| `sceneCursorFuse` | `true` | Whether the cursor uses gaze/dwell-based clicking (useful in VR without hand controllers). |
| `sceneCursorExtraParameters` | *(empty)* | Raw text appended as-is to the `cursor` attribute. |
| `sceneFog` | `false` | Any value other than the literal `false` enables scene fog — set to `true`. **Only takes effect when `environment:enable` is `false`** — the environment component (on by default) manages its own fog and overrides these settings, and there's currently no `<discovr>` attribute to configure or disable that. |
| `sceneFogType` | `none` | Fog component `type` — set this to `linear` or `exponential` when enabling `sceneFog` (the default `none` isn't a valid A-Frame fog type on its own). |
| `sceneFogColor` | `#000000` | Fog color. |
| `sceneFogNear` / `sceneFogFar` | `1` / `1000` | Distance range used by `linear` fog. |
| `sceneFogDensity` | `0.00025` | Density used by `exponential` fog. |
| `sceneReflectionDirectionalLight` | *(empty)* | **Turns the `reflection` component on**: it is only added to the scene when this has a value, and left empty there is no reflection. The value is a selector for the directional light entity the component reflects off of (e.g. `#dirlight`); the light is only used for WebXR lighting estimation, so a selector matching nothing still enables the reflection. **Note:** `defaultLights:true`'s directional light has `id="internalDirLight"`, not `dirlight` — if you use `defaultLights:true`, set this to `#internalDirLight`. |

```html
<discovr presets="sceneBackground:#87CEEB;sceneFog:true;sceneFogType:linear;sceneFogColor:#87CEEB;sceneFogNear:10;sceneFogFar:80"></discovr>
```

**Changing presets after the page has already loaded**: call `window.reapplyPresets({ ...changedKeys })`
with just the keys you're changing (or mutate `window.config.presets` directly and call
`window.reapplyPresets()` with no argument) to apply new values immediately, without reloading the
page. This works because every `presets` key maps to a real, live-reactive A-Frame attribute on the
scene itself — no other `<discovr>` attribute group supports this (they involve adding/removing whole
entities or loading external resources, which still need a full reload). One exception:
`sceneRendererAntialias` can't be changed after the page loads — it configures the WebGL canvas itself,
which A-Frame doesn't recreate on the fly.

```js
// e.g. from your own page's script, after DiscoVR has booted
window.reapplyPresets({ sceneBackground: "#222222", sceneFog: "false" });
```

### `interface`

UI chrome around the scene.

| Key | Default | Description |
|---|---|---|
| `title` | *(empty)* | If non-empty, shows a title overlay in the top-left corner. |
| `subTitle` | *(empty)* | Subtitle shown under `title`. |
| `userClick` | `false` | Shows a "click to enter" overlay (`userImage`) before starting the experience. Automatically shown regardless of this setting whenever `network:enable` is `true`. Required for background music to play — see `audio` below. |
| `userImage` | `images/discovr-ui-new.png` | Image shown by the `userClick` overlay. |
| `vrButton` | `true` | Set to `false` to hide A-Frame's built-in "Enter VR" button. |
| `embedded` | *(unset, behaves as `false`)* | Set to `true` when the scene is embedded in a small viewport (e.g. an iframe) — disables pointer-lock look-controls in favor of drag-to-look. The scene then leaves fullscreen mode and takes the size of its container, so **the page must give it a height** — otherwise it renders 0px tall (a blank page). For a page that is just the scene: `<style>html, body { height: 100%; margin: 0; } a-scene { display: block; width: 100%; height: 100%; }</style>`; inside a larger page, give the `<a-scene>` (or its container) an explicit size. |

### `network`

Multiplayer, powered by DiscoVR NET.

| Key | Default | Description |
|---|---|---|
| `enable` | `false` | Turns multiplayer on. Every other key in this group only matters when this is `true`. |
| `server` | *(empty)* | Address of the DiscoVR NET server, e.g. `server:wss://net.example.com`. Empty uses the legacy multiplayer server, which is being retired. Through DiscoVR NET, microphone, camera and screen sharing need a NET server with a media server (DiscoVR's own has one); without it those buttons are hidden. A page shown inside an iframe needs `allow="microphone; camera; display-capture"` on it. |
| `roomName` | a random `roomXXXXXXXX` string | The room visitors are placed into — give it a fixed value so multiple visitors land in the same room. |
| `showChat` | `false` | Shows the text chat panel. |
| `chatPosX` / `chatPosY` | `0` | Pixel offset of the chat panel. |
| `showCam` | `false` | Shows the webcam toggle. The camera starts off; the visitor turns it on. |
| `showMic` | `false` | Shows the microphone toggle. The microphone starts on (after the browser's permission prompt). |
| `showShare` | `false` | Shows the screen-share toggle (desktop browsers). |
| `showAvatarName` | `false` | Lets visitors see/set their avatar's display name. |
| `showAvatarColor` | `false` | Lets visitors set their avatar's color. |
| `disableNameChange` | `false` | Locks the avatar name so visitors can't change it (only meaningful alongside `showAvatarName:true`). |
| `positionalAudio` | `false` | Makes other visitors' voice audio positional (quieter as they move further away) instead of flat. |

### `playerRig`

The player's camera/movement rig. When disabled, a minimal fallback camera is used instead (with mouse-look and WASD movement, no VR controllers or teleport).

| Key | Default | Description |
|---|---|---|
| `enable` | `false` | Enables the full player rig: VR controllers, movement, teleport, and navmesh constraints. |
| `posX` / `posY` / `posZ` | `0` | Starting position. |
| `rotY` | `0` | Starting yaw rotation, in degrees. |

**As an entity instead of config.** `playerRig` is shorthand for this: `loadScene()` turns it into an `i-player-rig` entity. The same rig can be placed in the scene as an ordinary entity, with the `i-player-rig` component - where the player starts is then simply that entity's `position` and `rotation`:

```html
<a-entity i-player-rig position="0 0 4" rotation="0 30 0"></a-entity>
```

It builds exactly the rig `playerRig:enable` does (same `#cameraRig`, `#head` and hand controllers, same teleport and navmesh behavior). A scene has one player rig: the entity's id is forced to `cameraRig`, and if the page has both an `i-player-rig` entity and `playerRig:enable:true`, the entity wins. Optional properties, each defaulting to `auto` (follow the `<discovr>` tag): `embedded` (`true`/`false`), `teleport` (`true`/`false`), `collisionEntities` (selector for the surfaces visitors can teleport onto, `none` to skip collision testing) and `ignoreEntities` (selector for entities the teleport raycaster ignores) - so a rig can have its own teleport setup without touching the shared `teleport` group below, which stays the default for every rig that doesn't say otherwise.

### `teleport`

Only relevant when a player rig exists (`playerRig:enable`, or an `i-player-rig` entity - which can override `enable`, `collisionEntities` and `ignoreEntities` per rig).

| Key | Default | Description |
|---|---|---|
| `enable` | `true` | Enables teleport movement (click/trigger to teleport). |
| `cameraRig` | `#cameraRig` | Selector for the rig entity to move on teleport. |
| `cameraHead` | `#head` | Selector for the camera entity used to aim the teleport cursor. |
| `collisionEntities` | `.navmesh` | Selector for the surfaces visitors can teleport onto. Set to `none` to disable collision testing entirely. |
| `ignoreEntities` | `.raycastable` | Selector for entities the teleport raycaster should ignore. |

### `environment`

Passed through to the [aframe-environment-component](https://github.com/supermedium/aframe-environment-component).

| Key | Default | Description |
|---|---|---|
| `enable` | `true` | Adds the environment entity to the scene. |
| `preset` | `default` | Environment preset name (see the environment component's docs for the full list). |
| `shadow` | `true` | Enables shadows on the environment ground. |
| `groundColor` | `#0c3069` | Ground color. |
| `grid` | `1x1` | Ground grid density. |
| `gridColor` | `#424242` | Grid line color. |
| `stageSize` | `200` | Size of the environment stage. |
| `lighting` | `distant` | Lighting type used by the preset. |

### `audio`

Background music and the advanced (Tone.js-based) audio engine.

| Key | Default | Description |
|---|---|---|
| `advanced` | `false` | Loads Tone.js and enables the advanced audio engine. |
| `bgMusic` | `false` | Plays background music. **Only takes effect when `interface:userClick` is also `true`** — background audio needs a user gesture to start, which the click-to-enter overlay provides. |
| `bgMusicSrc` | *(empty)* | Path (relative to the DiscoVR host, or an absolute URL) to the background music file. |
| `bgMusicVolume` | `0.5` | Volume, from `0` to `1`. |

## Example

```html
<discovr
    presets="defaultScene:true;defaultLights:true"
    environment="preset:forest;groundColor:#2d4a1f"
    playerRig="enable:true"
    network="enable:true;roomName:my-fixed-room;showChat:true;showAvatarName:true"
    interface="userClick:true;title:My Experience"
    audio="bgMusic:true;bgMusicSrc:audio/theme.mp3;bgMusicVolume:0.3"
></discovr>
```

## What's next

- **[Programmatic scene building](discovr-class-api.md)** — the `DiscoVR` class, for building (part of) a scene in JavaScript instead of tag attributes.
- **[Examples](examples.md)** — complete pages putting these attributes to use.
