blocknote

Work with BlockNote, a block-based rich text editor for React. Use when the user mentions "blocknote", "BlockNote editor", "block-based editor", "insertBlocks", "updateBlock", "removeBlocks", "replaceBlocks", "editor.document", "InlineContent", "StyledText", "nestBlock", "unnestBlock", "addStyles", "toggleStyles", "removeStyles", "createLink", "getTextCursorPosition", "setTextCursorPosition", "getSelection", "setSelection", "forEachBlock", "useCreateBlockNote", "BlockNoteView", "paragraph block", "heading block", "bulletListItem", "PartialBlock", or asks how to manipulate blocks, style text, insert content, or read document structure in BlockNote.

40 stars

Best use case

blocknote is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Work with BlockNote, a block-based rich text editor for React. Use when the user mentions "blocknote", "BlockNote editor", "block-based editor", "insertBlocks", "updateBlock", "removeBlocks", "replaceBlocks", "editor.document", "InlineContent", "StyledText", "nestBlock", "unnestBlock", "addStyles", "toggleStyles", "removeStyles", "createLink", "getTextCursorPosition", "setTextCursorPosition", "getSelection", "setSelection", "forEachBlock", "useCreateBlockNote", "BlockNoteView", "paragraph block", "heading block", "bulletListItem", "PartialBlock", or asks how to manipulate blocks, style text, insert content, or read document structure in BlockNote.

Teams using blocknote should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/blocknote/SKILL.md --create-dirs "https://raw.githubusercontent.com/clasen/Skills/main/blocknote/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/blocknote/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How blocknote Compares

Feature / AgentblocknoteStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Work with BlockNote, a block-based rich text editor for React. Use when the user mentions "blocknote", "BlockNote editor", "block-based editor", "insertBlocks", "updateBlock", "removeBlocks", "replaceBlocks", "editor.document", "InlineContent", "StyledText", "nestBlock", "unnestBlock", "addStyles", "toggleStyles", "removeStyles", "createLink", "getTextCursorPosition", "setTextCursorPosition", "getSelection", "setSelection", "forEachBlock", "useCreateBlockNote", "BlockNoteView", "paragraph block", "heading block", "bulletListItem", "PartialBlock", or asks how to manipulate blocks, style text, insert content, or read document structure in BlockNote.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# BlockNote

Skill for working with [BlockNote](https://www.blocknotejs.org/), a block-based rich text editor for React.

## Core Mental Model

Everything in a BlockNote document is a **Block**. A paragraph is a block, a heading is a block, a list item is a block. Blocks can nest (children), and each block holds its rich text as an array of **InlineContent** objects.

```
Document
├── Block (paragraph)          ← top-level block
│   └── InlineContent[]        ← rich text inside
├── Block (heading)
│   └── InlineContent[]
└── Block (bulletListItem)
    ├── InlineContent[]
    └── Block (nested child)   ← indented sub-item
        └── InlineContent[]
```

## Block Type

```ts
type Block = {
  id: string;
  type: string;                                        // "paragraph" | "heading" | "bulletListItem" | ...
  props: Record<string, boolean | number | string>;    // type-specific properties
  content: InlineContent[] | TableContent | undefined; // rich text (undefined for images, columns)
  children: Block[];                                   // nested child blocks
};
```

When creating or updating blocks, use `PartialBlock` — all fields are optional:

```ts
editor.insertBlocks([{ type: "paragraph", content: "Hello!" }], refBlock);
editor.updateBlock(blockId, { props: { level: 2 } });
```

## InlineContent Types

```ts
type StyledText = { type: "text"; text: string; styles: Styles };
type Link      = { type: "link"; content: StyledText[]; href: string };
type InlineContent = StyledText | Link | CustomInlineContent;
```

`Styles` is a key/value map of active style attributes (e.g. `{ bold: true, textColor: "red" }`).

See [references/document-structure.md](references/document-structure.md) for full type definitions including `TableContent` and column blocks.

## Quick API Reference

### Reading

```ts
const all   = editor.document;                         // all top-level blocks
const block = editor.getBlock(id);                     // by id or Block ref
const prev  = editor.getPrevBlock(id);
const next  = editor.getNextBlock(id);
const parent = editor.getParentBlock(id);

editor.forEachBlock((block) => {
  console.log(block.id, block.type);
  return true;                                         // false stops traversal
});
```

### Inserting

```ts
// Insert before (default) or after a reference block
editor.insertBlocks(
  [{ type: "heading", content: "Title", props: { level: 2 } }],
  referenceBlock,
  "after",
);
```

### Updating

```ts
editor.updateBlock(blockId, { type: "heading", props: { level: 1 } });
editor.updateBlock(blockId, { content: "New text" });
```

### Removing & Replacing

```ts
editor.removeBlocks([id1, id2]);
editor.replaceBlocks([oldId], [{ type: "paragraph", content: "Replacement" }]);
```

### Moving & Nesting

```ts
editor.moveBlocksUp();
editor.moveBlocksDown();
if (editor.canNestBlock())   editor.nestBlock();
if (editor.canUnnestBlock()) editor.unnestBlock();
```

### Inline Content at Cursor

```ts
editor.insertInlineContent("plain text");
editor.insertInlineContent([
  { type: "text", text: "Bold", styles: { bold: true } },
  { type: "link", content: "BlockNote", href: "https://blocknotejs.org" },
]);
```

### Styles on Selection

```ts
editor.addStyles({ bold: true, textColor: "red" });
editor.removeStyles({ bold: true });
editor.toggleStyles({ italic: true });
const active = editor.getActiveStyles();               // styles at cursor / selection end
const text   = editor.getSelectedText();
```

### Links

```ts
editor.createLink("https://example.com");             // wraps selected text
editor.createLink("https://example.com", "Custom label");
const url = editor.getSelectedLinkUrl();
```

### Cursor & Selection

```ts
const pos = editor.getTextCursorPosition();           // { block, prevBlock, nextBlock, ... }
editor.setTextCursorPosition(blockId, "start");       // "start" | "end"
const sel = editor.getSelection();
editor.setSelection(startBlockId, endBlockId);
```

See [references/block-api.md](references/block-api.md) for the complete API reference with all parameters and examples.

## Common Patterns

### Insert block after the current cursor position

```ts
const { block } = editor.getTextCursorPosition();
editor.insertBlocks(
  [{ type: "paragraph", content: "Inserted after cursor" }],
  block,
  "after",
);
```

### Convert the current block to a heading

```ts
const { block } = editor.getTextCursorPosition();
editor.updateBlock(block, { type: "heading", props: { level: 2 } });
```

### Build a section programmatically

```ts
const anchor = editor.document[0];
editor.insertBlocks(
  [
    { type: "heading", content: "Section Title", props: { level: 2 } },
    { type: "paragraph", content: "Intro paragraph." },
    { type: "bulletListItem", content: "Item 1" },
    { type: "bulletListItem", content: "Item 2" },
  ],
  anchor,
  "after",
);
```

### Apply bold to selected text

```ts
editor.addStyles({ bold: true });
```

### Collect all blocks of a given type

```ts
const headings: Block[] = [];
editor.forEachBlock((block) => {
  if (block.type === "heading") headings.push(block);
  return true;
});
```

### Replace a block with a different type, preserving content

```ts
const block = editor.getBlock(blockId)!;
editor.replaceBlocks([block], [{ type: "heading", content: block.content, props: { level: 1 } }]);
```

## Key Gotchas

- **`content` can be `undefined`**: Image blocks, column blocks, and `columnList` blocks have no rich-text content — their `content` field is `undefined`. Always check before accessing.
- **`children` vs `content`**: Nested sub-blocks live in `children`, not `content`. `content` is only the inline rich text of the block itself.
- **`editor.document` is a snapshot**: It returns the document state at the time of the call. Subscribe to `onChange` to keep a reactive copy.
- **`PartialBlock` for writes**: When inserting or updating you never need to supply all fields. Omit anything you don't want to change.
- **`forEachBlock` is depth-first**: It traverses the entire tree including nested children, not just top-level blocks.
- **Column restrictions**: `columnList` children must be `column` blocks; `column` children must be regular blocks; a `columnList` needs at least 2 columns.
- **`moveBlocksUp/Down` acts on the selection**: Position the cursor or set a selection before calling these.

Related Skills

workflow-orchestration

40
from clasen/Skills

Orchestrates structured task execution with planning, progress tracking, self-improvement, and verification gates. Use at the start of any coding session, when given a non-trivial task (3+ steps or architectural decisions), when corrected by the user, when fixing bugs, or when the user mentions "plan", "todo", "track progress", "verify", "lessons learned", "fix this bug", or "task management". Applies to all coding workflows where structured methodology improves quality and reduces mistakes.

skill-builder

40
from clasen/Skills

Interactive guide for creating new agent skills from scratch. Use this skill when the user wants to create a skill, write a SKILL.md, package a skill folder, or convert an existing workflow into a reusable skill. Also trigger when the user mentions "create skill", "new skill", "SKILL.md", "teach the agent", or wants to standardize a repeatable process into a skill.

heavy-planner

40
from clasen/Skills

Creates high-clarity product and technical specifications by interrogating requirements before planning. Use when the user asks to "crear especificaciones", "write a spec", "define requirements", "hacer el plan", "scope a project", or shares an idea that is still vague. This skill asks exhaustive follow-up questions first and only proposes a structured plan after unknowns are surfaced.

workspace-surface-audit

144923
from affaan-m/everything-claude-code

Audit the active repo, MCP servers, plugins, connectors, env surfaces, and harness setup, then recommend the highest-value ECC-native skills, hooks, agents, and operator workflows. Use when the user wants help setting up Claude Code or understanding what capabilities are actually available in their environment.

DevelopmentClaude

ui-demo

144923
from affaan-m/everything-claude-code

Record polished UI demo videos using Playwright. Use when the user asks to create a demo, walkthrough, screen recording, or tutorial video of a web application. Produces WebM videos with visible cursor, natural pacing, and professional feel.

Developer ToolsClaude

token-budget-advisor

144923
from affaan-m/everything-claude-code

Offers the user an informed choice about how much response depth to consume before answering. Use this skill when the user explicitly wants to control response length, depth, or token budget. TRIGGER when: "token budget", "token count", "token usage", "token limit", "response length", "answer depth", "short version", "brief answer", "detailed answer", "exhaustive answer", "respuesta corta vs larga", "cuántos tokens", "ahorrar tokens", "responde al 50%", "dame la versión corta", "quiero controlar cuánto usas", or clear variants where the user is explicitly asking to control answer size or depth. DO NOT TRIGGER when: user has already specified a level in the current session (maintain it), the request is clearly a one-word answer, or "token" refers to auth/session/payment tokens rather than response size.

Productivity & Content CreationClaude

skill-comply

144923
from affaan-m/everything-claude-code

Visualize whether skills, rules, and agent definitions are actually followed — auto-generates scenarios at 3 prompt strictness levels, runs agents, classifies behavioral sequences, and reports compliance rates with full tool call timelines

DevelopmentClaude

santa-method

144923
from affaan-m/everything-claude-code

Multi-agent adversarial verification with convergence loop. Two independent review agents must both pass before output ships.

Quality AssuranceClaude

safety-guard

144923
from affaan-m/everything-claude-code

Use this skill to prevent destructive operations when working on production systems or running agents autonomously.

DevelopmentClaude

repo-scan

144923
from affaan-m/everything-claude-code

Cross-stack source code asset audit — classifies every file, detects embedded third-party libraries, and delivers actionable four-level verdicts per module with interactive HTML reports.

DevelopmentClaude

project-flow-ops

144923
from affaan-m/everything-claude-code

Operate execution flow across GitHub and Linear by triaging issues and pull requests, linking active work, and keeping GitHub public-facing while Linear remains the internal execution layer. Use when the user wants backlog control, PR triage, or GitHub-to-Linear coordination.

DevelopmentClaude

product-lens

144923
from affaan-m/everything-claude-code

Use this skill to validate the "why" before building, run product diagnostics, and pressure-test product direction before the request becomes an implementation contract.

Product ManagementClaude