Skip to main content
Extensions are the modular building blocks of Tiptap. Every feature in Tiptap is packaged as an extension, whether it’s a node (like paragraphs or headings), a mark (like bold or italic), or functionality (like history or placeholder).

What are Extensions?

Tiptap has three types of extensions:

Extensions

Generic extensions that add functionality without defining content structure (e.g., StarterKit, Placeholder, CharacterCount)

Nodes

Block or inline content types that make up your document (e.g., Paragraph, Heading, Image)

Marks

Formatting that can be applied to text (e.g., Bold, Italic, Link)
All three types share the same underlying Extendable base class and can be used interchangeably in the extensions array.

Using Extensions

Extensions are passed to the editor via the extensions option:

Configuring Extensions

Most extensions accept options that can be configured using the configure() method:

Extension Structure

Every extension is created using the Extension.create(), Node.create(), or Mark.create() static methods:
Source: /home/daytona/workspace/source/packages/core/src/Extension.ts:23

Extension API

Configuration

string
required
The unique name of the extension. This is used to identify the extension.
number
default:"100"
The priority determines the order in which extensions are loaded. Higher priority extensions are loaded first.
() => Options
Define default options for your extension.
() => Storage
Define storage that persists across the lifetime of the editor.
Access storage via editor.storage.extensionName:

Commands

() => Commands
Add commands that can be called via editor.commands.
Usage:

Keyboard Shortcuts

() => Record<string, () => boolean>
Add keyboard shortcuts for your extension.
Mod is Cmd on Mac and Ctrl on Windows/Linux.

Input Rules

() => InputRule[]
Add input rules for markdown-style shortcuts.
This would convert **text** to bold text as you type.

Paste Rules

() => PasteRule[]
Add paste rules for handling pasted content.

ProseMirror Plugins

() => Plugin[]
Add ProseMirror plugins to extend functionality.

Global Attributes

() => GlobalAttribute[]
Add attributes to multiple node or mark types.

Lifecycle Hooks

() => void
Called when the editor is created.
() => void
Called when the editor content changes.
() => void
Called when the selection changes.
({ transaction }) => void
Called for every transaction.
({ event }) => void
Called when the editor receives focus.
({ event }) => void
Called when the editor loses focus.
() => void
Called when the editor is destroyed. Use this to clean up resources.

Creating an Extension

Here’s a complete example of a custom extension:

Usage

Extending Extensions

You can extend existing extensions to modify or add functionality:
The this.parent?.() call merges the parent extension’s attributes with your new ones.

Extension Packages

Tiptap provides many official extensions:

Starter Kit

The StarterKit includes:
  • Document
  • Paragraph
  • Text
  • Bold
  • Italic
  • Strike
  • Code
  • Heading
  • Blockquote
  • BulletList
  • OrderedList
  • ListItem
  • CodeBlock
  • HardBreak
  • HorizontalRule
  • History
  • Dropcursor
  • Gapcursor

Individual Extensions

Real-World Example: Bold Extension

Here’s the actual implementation of the Bold extension from the Tiptap source:
Source: /home/daytona/workspace/source/packages/extension-bold/src/bold.tsx:56

TypeScript Support

Best Practices

Unique Names

Always use unique extension names to avoid conflicts.

Clean Up Resources

Use onDestroy to clean up event listeners, timers, and other resources.

Use TypeScript

Define types for your options and storage for better developer experience.

Test Thoroughly

Extensions can interact in unexpected ways. Test your extension with various combinations of other extensions.

Nodes & Marks

Learn about creating node and mark extensions

Commands

Learn about the command system

Schema

Learn about how extensions generate the schema

Editor

Learn about the Editor class