ExamplesCustom SchemasMacro Block

Macro Block

In this example, we create a custom Macro block using the vanilla createBlockSpec API from @blocknote/core. Each macro block stores an id prop, and the id is used to look up "before" and "after" HTML strings in a global map. Those strings are injected as html on either side of the editable inline content.

This pattern is useful when you want a block whose decoration is driven by a runtime registry — for example, server-driven labels, citations, or templated wrappers.

Try it out: Edit the inline text inside each macro block. Notice that the "before" and "after" decorations stay non-editable, and that swapping the id in App.tsx would change the surrounding HTML without touching the block's content.

Relevant Docs:

import { BlockNoteSchema, defaultBlockSpecs } from "@blocknote/core";import "@blocknote/core/fonts/inter.css";import { BlockNoteView } from "@blocknote/mantine";import "@blocknote/mantine/style.css";import { useCreateBlockNote } from "@blocknote/react";import { macroBlock } from "./Macro";import "./styles.css";const schema = BlockNoteSchema.create({  blockSpecs: {    ...defaultBlockSpecs,    macro: macroBlock(),  },});export default function App() {  const editor = useCreateBlockNote({    schema,    initialContent: [      {        type: "paragraph",        content:          "Below are two macro blocks. Each looks up its before/after content from a global registry by id — the first uses HTML strings, the second uses a live <input> element:",      },      {        type: "macro",        props: { id: "warning" },        content: "Stay hydrated while editing",      },      {        type: "macro",        props: { id: "note" },        content: "Type a note here, then add a label on the left",      },      {        type: "paragraph",        content: "Edit the inline text inside each macro to see it stay live.",      },    ],  });  return <BlockNoteView editor={editor} />;}