By Stephen Ou, creator of Fruition. Last Updated 9/15/2020.

<aside> 👇 An examination into Notion's data model that powers its impressive functionalities and intuitive UX.

</aside>

Introduction

This guide is a culmination of 4 weeks of research I did after falling in love with Notion. As a software engineer, I'm always curious about how an app works. Notion's impressive functionalities and intuitive UX captivated me, so I decided to learn it from first principles and document it publicly.

This guide assumes you know Notion's functionalities and are curious about how they work. This guide also assumes you have a basic understanding of a data structure.

Let's get started.

Blocks

The core foundation of Notion is built on the block model. If there's one thing to take away from this guide, it's how the block model works.

Text, headings, bullet list items, pages, embeds, a row in a database, an item in a Kanban board, etc. are all blocks. Blocks can contain other blocks, which form a hierarchy. Let's illustrate with examples.

The left side contains an example and some explanation.

The right side contains the block data structure for the example.


This is a page


{
  "id": "3c4cf4de-b18f-41f5-9ef3-fa2512b64778",
  "type": "page",
  "properties": {
    "title": [ [ "This is a page" ] ]
  },
  "content": ["1c4d57e7-c4ef-4014-937c-efc83352673c"],
  "format": {
    "page_icon": "🆒"
  }
}
...
{
  "id": "1c4d57e7-c4ef-4014-937c-efc83352673c",
  "type": "text",
  "properties": {
    "title": [ [ "This is page content" ] ]
  }
}

This is some text

This is some indented text

This is more indented text


{
  "id": "de255445-545d-49f7-af58-b44c853b27fc",
  "type": "text",
  "properties": {
    "title": [ [ "This is some text" ] ]
  },
  "content": [
    "7683406e-8895-4671-8ad3-e312346eb84a",
		"8de174e7-a8d4-47a6-95b8-1518a5c99f18"
  ]
}
...
{
  "id": "7683406e-8895-4671-8ad3-e312346eb84a",
  "type": "text",
  "properties": {
    "title": [ [ "This is some indented text" ] ]
  }
}
...
{
  "id": "8de174e7-a8d4-47a6-95b8-1518a5c99f18",
  "type": "text",
  "properties": {
    "title": [ [ "This is more indented text" ] ]
  }
}

This is some text with styling


{
  "id": "31bf5040-6e5b-4a59-8c2c-5e4bd996abff",
  "type": "text",
  "properties": {
    "title": [ [ "This is some text with styling" ] ]
  },
  "format": {
    "block_color": "purple_background"
  }
}

This is some text with inline formatting May 25, 2020 @Stephen Ou


{
  "id": "f5350525-8517-4f3b-8030-321a920300e2",
  "type": "text",
  "properties": {
    "title": [
      ["This",[["b"]]],
      [" "],
      ["is",[["i"]]],
      [" "],
      ["some",[["s"]]],
      [" "],
      ["text",[["c"]]],
      [" "],
      ["with",[["a","<https://notion.so>"]]],
      [" "],
      ["inline",[["h","red"]]],
      [" "],
      ["formatting",[["h","red_background"]]],
      [" "],
			["‣", [ [ "d", { "type": "date", "start_date": "2020-05-25", "date_format": "relative" } ] ] ],
      [" "],
			["‣", [ [ "u", "86dc633d-b388-40a0-b6c5-c4662525c20d" ] ] ]
    ]
  }
}

This is a heading

This is a sub-heading


{
  "id": "3c47498d-586c-47b9-92dd-66d7cc141381",
  "type": "header",
  "properties": {
    "title": [ [ "This is a heading" ] ]
  }
}
...
{
  "id": "c31961dc-8361-40c9-ae09-4486a16230f6",
  "type": "sub_header",
  "properties": {
    "title": [ [ "This is a sub-heading" ] ]
  }
}

{
  "id": "7651af72-4559-4f3a-b5b8-84265135e3d3",
  "type": "to_do",
  "properties": {
    "title": [ [ "This is a todo" ] ],
    "checked": [ [ "No" ] ]
  }
}

{
  "id": "885dffa9-5044-456c-bb3f-8ff7ac294783",
  "type": "bulleted_list",
  "properties": {
    "title": [ [ "This is a bulleted list item" ] ]
  },
  "content": ["03ca511c-20d6-4c10-82b5-ad670e88b511"]
}
...
{
  "id": "03ca511c-20d6-4c10-82b5-ad670e88b511",
  "type": "bulleted_list",
  "properties": {
    "title": [ [ "This is a sub-bulleted list item" ] ]
  }
}

{
  "id": "0aff5ab4-2dc1-4a5f-af8f-c63fd15ece06",
  "type": "toggle",
  "properties": {
    "title": [ [ "This is a toggled list item" ] ]
  },
  "content": [
    "b5030aba-f173-45fa-b571-bb822ba88e38"
  ]
}
...
{
  "id": "0aff5ab4-2dc1-4a5f-af8f-c63fd15ece06",
  "type": "text",
  "properties": {
    "title": [ [ "This is some hidden content." ] ]
  }
}