BlockNote Integration
BlockNote Databases can be embedded directly inside a BlockNote block-based editor. Each database block renders a fully interactive table view within the editor document.
Create a database block specification and register it with BlockNote:
import { BlockNoteSchema, defaultBlockSpecs } from "@blocknote/core";import { BlockNoteView } from "@blocknote/react";import { useCreateBlockNote } from "@blocknote/react";import "@blocknote/core/fonts/inter.css";import "@blocknote/react/style.css";import "@blocknote/block-view/react/styles.css";import "@blocknote/block-view/react/adapters/styles.css";
import { createDatabaseBlockSpec, insertDatabaseBlockItem } from "@blocknote/block-view/blocknote";import { InMemoryCollectionSource, InMemoryDocumentSource,} from "@blocknote/block-view/core/sources/in-memory";
// Create the block specificationconst databaseBlock = createDatabaseBlockSpec({ user: "user-1", initialize: async ({ collectionId }) => { // Return data sources for this collection const collectionSource = new InMemoryCollectionSource(getCollectionData(collectionId)); const documentSource = new InMemoryDocumentSource(getDocumentsData(collectionId)); return { collectionSource, documentSource }; },});
// Extend the BlockNote schemaconst schema = BlockNoteSchema.create({ blockSpecs: { ...defaultBlockSpecs, database: databaseBlock, },});Rendering the Editor
Section titled “Rendering the Editor”function MyEditor() { const editor = useCreateBlockNote({ schema, });
return ( <BlockNoteView editor={editor} slashMenu // enables the slash menu /> );}Slash Menu Integration
Section titled “Slash Menu Integration”Add a /database command to the slash menu:
import { insertDatabaseBlockItem } from "@blocknote/block-view/blocknote";
const editor = useCreateBlockNote({ schema, // The insertDatabaseBlockItem adds a "Database" option to the slash menu});
// In your BlockNoteView, the slash menu automatically includes the database item// when you use the schema that has the database block specinsertDatabaseBlockItem creates a slash menu entry that inserts a new database block. When selected, it creates a block with empty collectionId and collectionViewId props.
Block Properties
Section titled “Block Properties”Each database block stores three props:
| Prop | Type | Description |
|---|---|---|
collectionId | string | ID of the collection to display |
collectionViewId | string | ID of the specific view to use |
viewType | string | View type (default: "table") |
These are stored in the BlockNote document. The actual collection data lives in your data sources.
Collection Picker
Section titled “Collection Picker”When a database block is inserted without a collectionId, it needs a way for the user to select or create a collection. Provide a collectionPicker component:
const databaseBlock = createDatabaseBlockSpec({ user: "user-1", initialize: async ({ collectionId }) => ({ collectionSource: new InMemoryCollectionSource(getCollectionData(collectionId)), documentSource: new InMemoryDocumentSource(getDocumentsData(collectionId)), }), collectionPicker: ({ onSelect, onCancel }) => ( <div style={{ padding: 16, border: "1px solid #ddd", borderRadius: 8 }}> <p>Choose a collection:</p> <button onClick={() => onSelect("tasks")}>Tasks</button> <button onClick={() => onSelect("projects")}>Projects</button> <button onClick={onCancel}>Cancel</button> </div> ),});The picker receives onSelect(collectionId) to confirm a selection and onCancel to dismiss.
Shared Undo/Redo
Section titled “Shared Undo/Redo”By default, the BlockNote editor and embedded database tables have independent undo/redo stacks. Use GlobalUndoRedoManager to unify them — so Ctrl+Z undoes the most recent action regardless of whether it was a text edit or a database change.
import { GlobalUndoRedoProvider, GlobalUndoRedoExtension } from "@blocknote/block-view/blocknote";import { GlobalUndoRedoManager } from "@blocknote/block-view/core";
function MyEditor() { // Create a shared undo/redo manager const undoRedoManager = useMemo(() => new GlobalUndoRedoManager(), []);
const editor = useCreateBlockNote({ schema, extensions: [ // Register BlockNote's undo/redo with the global manager GlobalUndoRedoExtension.configure({ globalUndoRedoManager: undoRedoManager }), ], });
return ( <GlobalUndoRedoProvider value={undoRedoManager}> <BlockNoteView editor={editor} /> </GlobalUndoRedoProvider> );}The GlobalUndoRedoProvider context makes the shared manager available to all database blocks rendered inside the editor. Each database block automatically registers its own UndoRedoManager as a source.
Multiple Database Blocks
Section titled “Multiple Database Blocks”A single editor can contain multiple database blocks, each showing a different collection or a different view of the same collection:
// Initial editor content with multiple database blocksconst initialContent = [ { type: "heading", content: "Project Overview", }, { type: "database", props: { collectionId: "tasks", collectionViewId: "view-1", viewType: "table", }, }, { type: "paragraph", content: "Here's the team roster:", }, { type: "database", props: { collectionId: "team-members", collectionViewId: "view-2", viewType: "table", }, },];
const editor = useCreateBlockNote({ schema, initialContent,});Each block independently initializes its CollectionManager using the initialize function you provided to createDatabaseBlockSpec. They share the same GlobalUndoRedoManager if you set one up.
Full Example
Section titled “Full Example”import { useMemo } from "react";import { BlockNoteSchema, defaultBlockSpecs } from "@blocknote/core";import { BlockNoteView, useCreateBlockNote } from "@blocknote/react";import "@blocknote/core/fonts/inter.css";import "@blocknote/react/style.css";import "@blocknote/block-view/react/styles.css";import "@blocknote/block-view/react/adapters/styles.css";
import { createDatabaseBlockSpec, insertDatabaseBlockItem, GlobalUndoRedoProvider, GlobalUndoRedoExtension,} from "@blocknote/block-view/blocknote";import { GlobalUndoRedoManager } from "@blocknote/block-view/core";import { InMemoryCollectionSource, InMemoryDocumentSource,} from "@blocknote/block-view/core/sources/in-memory";
// Your data loading functionsimport { getCollectionData, getDocumentsData } from "./my-data";
const databaseBlock = createDatabaseBlockSpec({ user: "user-1", initialize: async ({ collectionId }) => ({ collectionSource: new InMemoryCollectionSource(getCollectionData(collectionId)), documentSource: new InMemoryDocumentSource(getDocumentsData(collectionId)), }),});
const schema = BlockNoteSchema.create({ blockSpecs: { ...defaultBlockSpecs, database: databaseBlock, },});
export default function App() { const undoRedoManager = useMemo(() => new GlobalUndoRedoManager(), []);
const editor = useCreateBlockNote({ schema, extensions: [GlobalUndoRedoExtension.configure({ globalUndoRedoManager: undoRedoManager })], });
return ( <GlobalUndoRedoProvider value={undoRedoManager}> <BlockNoteView editor={editor} /> </GlobalUndoRedoProvider> );}