---
sidebar_position: 3
---

# App Pages and DOM Structure

This page maps the app routes and important DOM areas. It is useful for plugin authors, testers, and contributors who need stable mental models of where UI mounts.

## Angular Routes

| Route                        | Component                 | Purpose                                                               |
| ---------------------------- | ------------------------- | --------------------------------------------------------------------- |
| `/`                          | Redirect                  | Redirects to `/search`.                                               |
| `/login`                     | `LoginComponent`          | User login.                                                           |
| `/register`                  | `RegisterComponent`       | User registration.                                                    |
| `/invite/:inviteId`          | `InviteComponent`         | Resolve and accept invite links.                                      |
| `/search`                    | `ServerSearchComponent`   | Search and join servers.                                              |
| `/room/:roomId`              | `ChatRoomComponent`       | Main server page with text, voice, members, and plugin panels.        |
| `/dm`                        | `DmWorkspaceComponent`    | Direct-message workspace.                                             |
| `/dm/:conversationId`        | `DmWorkspaceComponent`    | A selected direct-message conversation.                               |
| `/settings`                  | `SettingsComponent`       | App, voice, server, plugin, desktop, theme, local API settings.       |
| `/plugin-store`              | `PluginStoreComponent`    | Browse plugin sources and install/update plugins.                     |
| `/plugins/:pluginId/:pageId` | `PluginPageHostComponent` | Host for plugin app pages registered with `api.ui.registerAppPage()`. |

## Page Shell

The renderer is an Angular app. The common shell contains router outlet content plus persistent app surfaces such as the server rail, title bar integrations, settings modals, and floating voice controls.

High-level structure:

```html
<app-root>
  <router-outlet></router-outlet>
  <!-- global dialogs, overlays, floating voice controls, and desktop integrations -->
</app-root>
```

## Server Page DOM

The server page is the most important page for plugins.

```html
<app-chat-room>
  <app-servers-rail></app-servers-rail>
  <app-rooms-side-panel>
    <section>Text Channels</section>
    <section>Voice Channels</section>
    <section data-testid="plugin-room-side-panel">
      <button>View plugins</button>
      <app-plugin-render-host></app-plugin-render-host>
    </section>
    <section>Members</section>
  </app-rooms-side-panel>
  <main>
    <app-voice-workspace></app-voice-workspace>
    <app-chat-messages>
      <app-message-list></app-message-list>
      <app-typing-indicator></app-typing-indicator>
      <app-message-composer></app-message-composer>
      <app-klipy-gif-picker></app-klipy-gif-picker>
    </app-chat-messages>
  </main>
</app-chat-room>
```

## Text Channel Area

Text channel UI is owned by the chat domain.

```html
<app-chat-messages>
  <app-message-list>
    <app-message-item></app-message-item>
  </app-message-list>
  <app-message-overlays></app-message-overlays>
  <app-typing-indicator></app-typing-indicator>
  <app-message-composer></app-message-composer>
</app-chat-messages>
```

Plugin touchpoints:

- `api.ui.registerComposerAction()` adds composer actions.
- `api.ui.registerEmbedRenderer()` renders declared custom embed payloads.
- `api.ui.mountElement()` can mount into a selector such as `app-chat-messages` when the plugin has `ui.dom`.

## Voice Area

Voice UI is split between channel membership, controls, and media workspace.

```html
<app-rooms-side-panel>
  <section>Voice Channels</section>
</app-rooms-side-panel>
<app-voice-controls></app-voice-controls>
<app-floating-voice-controls></app-floating-voice-controls>
<app-voice-workspace>
  <app-voice-workspace-stream-tile></app-voice-workspace-stream-tile>
</app-voice-workspace>
```

Plugin touchpoints:

- `api.media.playAudioClip()` plays local audio.
- `api.media.addCustomAudioStream()` contributes audio to voice handling.
- `api.media.addCustomVideoStream()` contributes a video stream.
- `api.channels.addAudioChannel()` creates a voice channel entry when the plugin has channel management rights.

## Plugin Store and Manager DOM

```html
<app-plugin-store>
  <!-- source management, search, plugin cards, install/update/uninstall actions -->
</app-plugin-store>

<app-plugin-manager>
  <!-- installed plugins, capability grants, activate/reload/unload, logs, docs -->
</app-plugin-manager>
```

Plugin pages registered through `api.ui.registerAppPage()` render at `/plugins/:pluginId/:pageId`:

```html
<app-plugin-page-host>
  <app-plugin-render-host></app-plugin-render-host>
</app-plugin-page-host>
```

## Plugin Render Host

`PluginRenderHostComponent` accepts plugin render functions that return either an `HTMLElement` or a string. Returning an `HTMLElement` is preferred for interactive UI. Returned strings are rendered as simple text content.

## Stable Selectors for Tests and Plugins

Prefer plugin APIs over DOM selectors. When direct DOM mounting is necessary, use stable app selectors and keep cleanup through the returned disposable.

Common targets:

| Selector                                 | Area                                                                                                                  |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `body`                                   | Global overlays or modals.                                                                                            |
| `app-chat-messages`                      | Main text channel surface.                                                                                            |
| `app-rooms-side-panel`                   | Server side panel.                                                                                                    |
| `[data-testid="plugin-room-side-panel"]` | Plugin side-panel area in the server sidebar, including the View plugins trigger for `registerToolbarAction()` tiles. |

Avoid depending on Tailwind utility classes; they are layout details and may change.
