---
title: "Blok Data Model — Everything Is a Block"
description: "How Blok stores content as nested JSON blocks with parentId and contentIds, and why there is no HTML in the document."
source: https://blokeditor.com/docs/concepts/
lastmod: 2026-09-07
---

Framework JavaScript

Getting started Everything is a block

# Everything is a block: Blok's data model

Blok has one core idea. Understand it, and the rest of the API falls into place.

Last updated Jun 30, 2026 [Edit this page on GitHub](https://github.com/JackUait/blok/blob/main/docs/src/components/api/ConceptsContent.tsx)

In Blok, every piece of content is a block. There is no separate document model running alongside them — blocks are the universal primitive. A paragraph is a block. A heading is a block. A whole database, and every row inside it, is a block. Once this clicks, the API stops reading like a list of features and starts reading like one consistent tree.

## The shape of a block

Every block — whatever its type — is the same small object. `type` names the tool that renders it, `data` holds that tool's content, and `tunes` holds optional block-level settings.

TypeScript

```
// Every block — whatever its type — is the same small object
{
  id: 'block-a1b2c3',              // unique, auto-generated
  type: 'paragraph',              // which tool renders it
  data: { text: 'Hello, world' }, // the tool's content
  tunes: {},                      // block-level settings (optional)
}
```

## Blocks form a tree

Blocks aren't a flat list. Any block can contain other blocks through `contentIds`, and each child points back through `parentId`. A block that holds children is, in effect, a page — opening it means navigating into its children.

TypeScript

```
// A database block holds its rows as children.
// In saved JSON the hierarchy fields are named `content` and `parent`;
// on live Block objects (and the React BlockNode) the same links are
// exposed as `contentIds` and `parentId`.
{
  id: 'db-1',
  type: 'database',
  data: { schema: [/* columns */], views: [/* configs */] },
  content: ['row-1', 'row-2'], // its children
}

// A row is a block that points back to its parent
{
  id: 'row-1',
  type: 'database-row',
  parent: 'db-1',
  data: { properties: { status: 'Done', priority: 'High' } },
}
```

## The same idea, all the way up

Features that look like separate systems are really just blocks arranged in the tree:

| This… | …is a block because |
| --- | --- |
| A paragraph | Its `data` holds the text and inline formatting. |
| A database | Its `data` holds the schema and view configs — not a side table. |
| A database row | It's a child of the database block; its values live in `data.properties`. |
| A page | Any block with children. Opening it navigates into its `contentIds`. |

## What is not a block

Structured property values — a status, a priority, a due date on a row — are not blocks. They're metadata stored in the owning block's `data`. The rule of thumb: if it has an identity, stores content, and can be nested, it's a block; if it's a typed value that belongs to a block, it lives in that block's `data`.

## Why this matters to you

Because everything is a block, you learn one set of moves and they work everywhere:

One API for everything

`insert`, `move`, and `delete` operate on any block — a paragraph, a row, or a whole database — with the same calls.

One save format

`editor.save()` walks the same tree for every kind of content, so persistence and rendering never need special cases.

One nesting model

`parentId` and `contentIds` describe containment everywhere, so a row inside a database and a paragraph inside a toggle behave the same way.

## Extending Blok? Ask one question

Before designing a new feature, ask: “Is this a block?” If it represents content, data, or a container, the answer is almost always yes — build it as a block instead of inventing a parallel data model.

- A calendar view → a view config on a database block; the rows stay row blocks.
- A comment thread → a block.
- A table of contents → a block that reads its sibling blocks.
- An embed → a block.

Ready to work with the tree directly? See the [Blocks API](https://blokeditor.com/docs/blocks-api/) for inserting and moving blocks, and [BlockData](https://blokeditor.com/docs/block-data/) for the exact shape of a saved block.
