# Mounting the Stream

## The `rootElement`

`appStream.rootElement` is the DOM element that contains the video player and all SDK UI components. You must append it to your page for the stream to be visible.

## When to Mount

Mount the `rootElement` inside the `onVideoInitialized` callback. This ensures the video element is ready before you add it to the DOM:

```javascript
appStream.onVideoInitialized = () => {
  document.getElementById('video-container').appendChild(appStream.rootElement);
};
```

## Configuring the Video Element

After mounting, you may want to configure the video element:

{% code lineNumbers="true" %}

```javascript
appStream.onVideoInitialized = () => {
  document.getElementById('video-container').appendChild(appStream.rootElement);

  // Access the video element
  const video = appStream.stream.videoElementParent.querySelector('video');
  if (video) {
    video.muted = true;       // Start muted (recommended for autoplay)
    video.autoplay = true;
    video.tabIndex = 0;       // Make focusable for keyboard input
    video.focus();            // Focus for immediate keyboard capture
  }

  // Mute the separate audio element
  const audio = appStream.stream._webRtcController?.streamController?.audioElement;
  if (audio) {
    audio.muted = true;
  }
};
```

{% endcode %}

## Hiding the Default Pixel Streaming UI

The SDK inherits some default UI elements from Epic Games' Pixel Streaming library. You'll typically want to hide these and build your own:

{% hint style="warning" %}
The `#uiFeatures` element may re-appear after the video initializes. You must hide it both after SDK initialization and inside the `onVideoInitialized` callback to ensure it stays hidden.
{% endhint %}

```javascript
// Hide after SDK initialization
const uiFeatures = appStream.uiFeaturesElement
  || appStream.rootElement?.querySelector('#uiFeatures');
if (uiFeatures) uiFeatures.style.display = 'none';

// Also hide after mounting (the element may re-appear)
appStream.onVideoInitialized = () => {
  document.getElementById('video-container').appendChild(appStream.rootElement);

  const uiEl = appStream.rootElement?.querySelector('#uiFeatures');
  if (uiEl) uiEl.style.display = 'none';
};
```

You can also use CSS:

```css
#uiFeatures {
  display: none !important;
}

#afkOverlay {
  display: none !important;
}
```

## The `onDisconnect` Callback

Called when the stream disconnects:

```javascript
appStream.onDisconnect = () => {
  // Show your disconnected UI
  document.getElementById('video-container').innerHTML = '';
  showDisconnectedMessage();
};
```

## Full-Screen Video Container

For a full-viewport stream, style your container:

```css
body {
  margin: 0;
  overflow: hidden;
}

#video-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
}

/* Ensure the SDK video fills the container */
#video-container video {
  width: 100%;
  height: 100%;
  object-fit: fill;
}
```
