Best way to store alot of data

Hi. I’m working on my first Yjs project (Love it so far).
The project is a block based note editor (Like Notion or Blocky-editor). The idea is you will create a workspace which will contain multiple pages. Each “page” is a instance of the Core and gets populated by the Awareness plugin depending on its Id (page_id in “Block.parents”). The reason a “Block” can have multiple parents is because I would like to be able to have “Synced Blocks” (Like Notion).

I have taken an event based approach to it so my general structure is like this:

  • Core: Manages the instances and plugins
  • Instance: Gets created by the core when a new “Block” (Referenced below) is created
  • Awareness: A plugin for the Core that listens to new instances being created and when an instance creates a new editor (Quill Js). When new editors are created I create a new Yjs version of my “Block” that is flattened to allow for easier data structuring and less memory usage (I think this is the case since there wont be nested maps?). NOTE: Core doesn’t require Awareness to work, Awareness is a plugin which is only supposed to bring collaboration & persistence to the editor.

My actual question:
How would I need to structure the data to be able to achieve this structure?

My current idea is to store all blocks under the Y.Doc as Maps (Encoded Block is described below). I’m assuming this would cause all of the Blocks to be loaded into memory when loading the Y.Doc (Even with a provider like y-websocket or Indexeddb) which would not be optimal. There would then be an Array associated with the page_id where the “Block” ids would be saved so that I can get them from the Y.Doc. I will observe all “Encoded Blocks” to update the instance when a user in the network makes a change.

I have played with the idea of using sub documents for each page, I believe this would eliminate the sync “Block” idea but if it is a must for a more scalable note editor I’m just going to have to live with that.

“Block”

{
    "id": "test",
    "order": "0",
    "type": "paragraph",
    "properties": {
        "content": "Hello World",
        "table": [
            [
                {
                    "content": "Cell 1 Row 1",
                    "width": "100"
                },
                {
                    "content": "Cell 2 Row 1",
                    "width": "100"
                }
            ],
            [
                {
                    "content": "Cell 1 Row 2",
                    "width": "100"
                },
                {
                    "content": "Cell 2 Row 2",
                    "width": "100"
                }
            ],
            [
                {
                    "content": "Cell 1 Row 3",
                    "width": "100"
                },
                {
                    "content": "Cell 2 Row 3",
                    "width": "100"
                }
            ],
            [
                {
                    "content": "Cell 1 Row 4",
                    "width": "100"
                },
                {
                    "content": "Cell 2 Row 4",
                    "width": "100"
                }
            ]
        ],
        "columns": [
            {
                "content": "Column 1"
            },
            {
                "content": "Column 2"
            },
            {
                "content": "Column 3"
            },
            {
                "content": "Column 4"
            },
            {
                "content": "Column 5"
            }
        ]
    },
    "content": [],
    "parents": {
        "page_id": "parent_id"
    }
}

Encoded “Block” (Today each value is a Y.Text. I could proberbly get away with not having any Y.Text and instead just observing the Map for changes)

{
    "i": "test",
    "o": "0",
    "t": 4,
    "p.c": "Hello World",
    "p.t.1.1.c": "Cell 1 Row 1",
    "p.t.c.1.w": "100",
    "p.t.1.2.c": "Cell 2 Row 1",
    "p.t.c.2.w": "100",
    "p.t.2.1.c": "Cell 1 Row 2",
    "p.t.2.2.c": "Cell 2 Row 2",
    "p.t.3.1.c": "Cell 1 Row 3",
    "p.t.3.2.c": "Cell 2 Row 3",
    "p.t.4.1.c": "Cell 1 Row 4",
    "p.t.4.2.c": "Cell 2 Row 4",
    "p.co.1.c": "Column 1",
    "p.co.2.c": "Column 2",
    "p.co.3.c": "Column 3",
    "p.co.4.c": "Column 4",
    "p.co.5.c": "Column 5",
    "pa.page_id": "parent_id"
}