Skip to content

feat: complex content exploration#2707

Draft
nperez0111 wants to merge 1 commit intomainfrom
feat/content-schemas
Draft

feat: complex content exploration#2707
nperez0111 wants to merge 1 commit intomainfrom
feat/content-schemas

Conversation

@nperez0111
Copy link
Copy Markdown
Contributor

This PR explores the possibility of introducing more complex custom content types.

Summary

Taking a table as an example:

[
  {
    "id": "abc",
    "type": "table",
    "content": {
      "type": "tableContent",
      "rows": [
        {
          "cells": [
            {
              "type": "tableCell",
              "content": [
                {
                  "type": "text",
                  "text": "a",
                  "styles": {}
                }
              ]
            }
          ]
        },
        {
          "cells": [
            {
              "type": "tableCell",
              "content": [
                {
                  "type": "text",
                  "text": "b",
                  "styles": {}
                }
              ]
            }
          ]
        }
      ]
    },
    "children": []
  }
]

What would happen if we decided to make this pattern more generic & exposed to the end developer? It could maybe look something like this:

createBlockSpec({
	type: 'table',
	content: c.customContentType('tableContent', c.record({
		rows: c.arrayOf(c.customContentType('tableCell', c.record({
			content: c.inline()
		})))
	}))
})

This sort of a structure would allow for representing arbitrarily complex relationships and enables multiple "slots" for content to be inserted within.

This is very powerful, but presents several challenges:

  • This would require creating intermediate prosemirror nodes, and their shapes and configuration should be cleanly defined (hopefully without exposing that complexity to the API)
  • There will be many edge cases with how this works UX-wise, this will inevitably force us to expand to a much more complex API surface than we currently expose
  • This encourages divergent schemas where no two editors have the same schema, hurting interoperability

Rationale

I explored a few different approaches for this, and none were satisfying to me. It felt like we were simple re-packaging what ProseMirror can represent, and drifting away from the benefits that BlockNote touts.

Some more exploration would be needed for this to actually be considered a viable solution for BlockNote. It simply is largely in contradiction of the goals of BlockNote.

Introduce ContentType abstraction and POJO combinator API (`c.inline`,
`c.none`, `c.record`, `c.list`, `c.blocks`, `c.props`) for declaring
arbitrary block content shapes — multi-slot records, variable-length
lists, regions of editor blocks, and typed per-item props. Block JSON
shapes are derived directly from the schema.

Phase 1 rebuilds the table block on top of the new ContentType primitive
with no observable behaviour or JSON-shape change. Phase 3 ships the
combinator surface, widens createReactBlockSpec to accept ContentType,
and adds 4 runnable examples (multi-slot alert, FAQ, callout, tab group)
plus end-to-end tests for the React render path and the data layer.

Also fixes textCursorPosition's parent walk-up to traverse multiple
non-bnBlock layers, which combinator slot chains can introduce.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blocknote Ready Ready Preview May 5, 2026 0:50am
blocknote-website Error Error May 5, 2026 0:50am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 73cbafd7-5725-41f6-bc5c-d22666d7125d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/content-schemas

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant