Skip to content
Greta.Agency
Case Studies

BlockNote Slash Commands & @mentions: Full Dev Integration Guide

Step-by-step guide to implementing slash commands and @blocknote/react in your editor. Covers BlockNote, TipTap, ProseMirror, and real-time sync with code examples.

MichaelApril 7, 20264 min read

Feature Overview

Notion's editor is a block-based document system. Every piece of content — a paragraph, a heading, a to-do item, a database, an image — is a "block" with a type and properties. Blocks can be nested, reordered, transformed into other block types, and synced in real time across multiple users.

This architecture is what makes Notion flexible enough to be a doc tool, a project tracker, a wiki, and a database — all in one product.

The Block Data Model

Every Notion page is a tree of blocks:

interface Block {
  id: string;
  type: 'paragraph' | 'heading_1' | 'heading_2' | 'bulleted_list' | 
        'numbered_list' | 'todo' | 'toggle' | 'code' | 'image' | 
        'database' | 'callout' | 'divider';
  properties: Record<string, any>; // type-specific content
  children: string[]; // ordered list of child block IDs
  parent_id: string | null;
  created_at: string;
  updated_at: string;
}

// Example paragraph block
{
  id: "abc123",
  type: "paragraph",
  properties: {
    rich_text: [
      { type: "text", text: "Hello ", bold: false },
      { type: "text", text: "world", bold: true }
    ]
  },
  children: [],
  parent_id: "page_xyz"
}

The rich_text array within a block handles inline formatting — bold, italic, code, links — without a separate node type for each. This keeps the block tree flat while supporting rich inline content.

Tech Approach

Option 1: Build on BlockNote (Recommended)

BlockNote is an open-source Notion-like editor built on TipTap and ProseMirror. It handles:

  • Block types (paragraph, heading, list, code, image)
  • Slash commands (/ menu to insert block types)
  • Drag-and-drop reordering
  • Markdown shortcuts
import { BlockNoteEditor } from "@blocknote/core";
import { BlockNoteView, useBlockNote } from "@blocknote/react";

function Editor() {
  const editor = useBlockNote({
    onEditorContentChange: (editor) => {
      const blocks = editor.topLevelBlocks;
      saveToDatabase(blocks);
    }
  });
  
  return <BlockNoteView editor={editor} />;
}

Building on BlockNote gives you 80% of Notion's editor in 1–2 days.

Option 2: Build on TipTap directly

TipTap is lower-level than BlockNote — you define your own node types, extensions, and commands. More flexibility, more work.

Use TipTap when you need custom block types that BlockNote doesn't support (like Notion's databases, or specialized chart blocks).

Option 3: Build from scratch with ProseMirror

Only if you have specific requirements that existing libraries can't meet. ProseMirror is the foundation under TipTap — extremely powerful, extremely complex. 8–12 weeks minimum to build a production editor.

Real-Time Collaboration

Adding collaborative editing (multiple cursors, conflict-free concurrent edits) requires a CRDT (Conflict-free Replicated Data Type) — specifically Yjs, which both BlockNote and TipTap support natively.

import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';

const ydoc = new Y.Doc();
const provider = new WebsocketProvider(
  'wss://your-yjs-server.com',
  'document-room-id',
  ydoc
);

// BlockNote integration
const editor = useBlockNote({
  collaboration: {
    provider,
    fragment: ydoc.getXmlFragment("document-store"),
    user: { name: "Alice", color: "#7CFC00" }
  }
});

The Yjs provider handles operational transforms — when two users edit the same paragraph simultaneously, both edits are merged correctly without conflicts or lost data.

Slash Commands

The / menu is the UX pattern that makes block editors discoverable. Implementation:

// BlockNote handles this natively
// For TipTap, use the @tiptap/suggestion extension
const slashCommands = [
  { title: "Heading 1", command: ({ editor }) => editor.chain().toggleHeading({ level: 1 }).run() },
  { title: "To-do list", command: ({ editor }) => editor.chain().toggleTaskList().run() },
  { title: "Code block", command: ({ editor }) => editor.chain().toggleCodeBlock().run() },
];

Simplified Steps to Ship

Week 1:

  • Set up BlockNote with your tech stack
  • Implement save/load from your database
  • Add the core block types your use case needs

Week 2:

  • Add real-time collaboration with Yjs (if needed)
  • Implement presence indicators (user avatars on shared docs)
  • Add image upload (Supabase Storage or Cloudinary)

Week 3:

  • Custom block types specific to your product
  • Export functionality (Markdown, PDF)
  • Version history (save snapshots on each edit, allow revert)

Estimated Complexity

| Feature | Complexity | Time | |---|---|---| | Basic rich text editor (BlockNote) | Low | 1–2 days | | Custom block types | Medium | 3–5 days | | Real-time collaboration | High | 1 week | | Full Notion-like system with databases | Very High | 6–10 weeks |

READY TO SHIP?

Build your MVP faster

Join founders using Greta to launch products in weeks, not months. Get a working prototype to test with real users — fast.

TALK TO A FOUNDER

Not sure where to start?

Book a 20-minute call. We'll map out your scope, tech stack, and go-to-market plan — for free.