> For the complete documentation index, see [llms.txt](https://docs.theopenpresenter.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.theopenpresenter.com/introduction/project-topology.md).

# Project Topology

The main bulk of a project lives within a Yjs Document. The structure of the document can be seen in our Typescript type here: <https://github.com/Vija02/TheOpenPresenter/blob/main/packages/base-plugin/src/types.ts>

Here's how a project document might look like:

{% code overflow="wrap" %}

```json
{
  "meta": {
    "id": "project_01j96y7vz1f5c9pphfx0nkqg6h",
    "name": "Test Project",
    "createdAt": "2024-10-02T15:40:36.706Z"
  },
  "data": {
    "scene_01j9c3wn6mfcpafk2ee8jwcw5t": {
      "name": "Audio Recorder",
      "order": 1,
      "type": "scene",
      "children": {
        "plugin_01j9c3wn6mfcpafk2eecfj37s5": {
          "plugin": "audio-recorder",
          "order": 1,
          "pluginData": {
            "recordings": [],
            "activeStreams": []
          }
        }
      }
    },
    "scene_01j9740ysfemzsdyvqn2pyhb5m": {
      "name": "Radio",
      "order": 2,
      "type": "scene",
      "children": {
        "plugin_01j9740ysge6wv45h29rqkddtt": {
          "plugin": "radio",
          "order": 1,
          "pluginData": {
            "url": ""
          }
        }
      }
    }
  },
  "renderer": {
    "1": {
      "currentScene": "scene_01jbf18xagf24a30sf1wvf19wh",
      "overlay": null,
      "children": {
        "scene_01j9740ysfemzsdyvqn2pyhb5m": {
          "plugin_01j9740ysge6wv45h29rqkddtt": {
            "volume": 0.05,
            "isPlaying": false
          }
        },
        "scene_01j9c3wn6mfcpafk2ee8jwcw5t": {
          "plugin_01j9c3wn6mfcpafk2eecfj37s5": {}
        }
      }
    }
  }
}
```

{% endcode %}

{% hint style="warning" %}
Some parts of this document might still change. Particularly around `meta` and  `renderer`
{% endhint %}

## ID

All ID inside our document should be a [TypeID](https://github.com/jetify-com/typeid-js). Notice that they are also prefixed with strings like *scene*, *plugin* and *project*.

## Meta

The **meta** object stores any meta information about the project. It is quite basic at the moment but we may add more things in the future.

## Data

The majority of information is stored in the **data** object. A project can contain many scenes.

#### Scene

A scene controls what is shown in a single view. It contains one or more **plugins.**

#### Plugin

Each plugin is responsible for a specific functionality. Eg: Video playing. You can include multiple plugin inside a single scene.&#x20;

For example, you may have a plugin to show a moving background. And then use another plugin to show text on top of it.

Crucially, each plugin can store its own data in the document. This data will be used by the Renderer to render the right things.

## Renderer

#### Multiple Views

A project have many views at any single time. This is useful to show different views to multiple screens. For example, to be used as a confidence monitor.

This is the first level under renderer.

#### Active scene

Each view will show the scene that is set in the **currentScene** property.

Meanwhile, the **overlay** property is used to override/overlay the view with something else like a black screen.

#### Children

The children property maps the **scenes** and **plugins** that exists in **data**. Correspondingly, each plugin is responsible for the data that is stored inside those properties.

{% hint style="info" %}
While we have the concept of **views** and **active scenes**, a plugin does not have to strictly obey them. For example, an song player plugin probably wants to keep playing across scenes. However, we encourage to keep crossovers to the minimum.
{% endhint %}

## Custom state in data vs renderer

So there are 2 location where plugin can store their state. When should you store state in **data** vs **renderer**?

If your data will be the same across views, they should be stored in **data**.

If your data will be different across views, they should be stored in **renderer**.

**For example:**

A lyrics plugin may store its songs in the **data** property. However, it may choose to store the display information in the **renderer** property. This allows users to show different lyrics of the same song in screens within the same plugin.
