---
title: "Migrate from Editor.js to Tiptap"
description: "Learn how to migrate your existing Editor.js editor to Tiptap. Complete guide covering content migration, setup, and feature mapping."
canonical_url: "https://tiptap.dev/docs/guides/migrate-from-editorjs"
---

# Migrate from Editor.js to Tiptap

Learn how to migrate your existing Editor.js editor to Tiptap. Complete guide covering content migration, setup, and feature mapping.

If you want to replace your Editor.js editor, Tiptap is a popular alternative.Migrating from Editor.js to Tiptap is straightforward. This guide will help you transition from Editor.js's block-based structure to Tiptap's document model.

## Content migration

### HTML content compatibility

Editor.js uses a block-based JSON structure that needs to be converted to HTML for Tiptap:

```ts
// Convert Editor.js blocks to HTML
function editorJsToHtml(editorJsData) {
  let html = ''

  editorJsData.blocks.forEach((block) => {
    switch (block.type) {
      case 'paragraph':
        html += `<p>${block.data.text}</p>`
        break
      case 'header':
        html += `<h${block.data.level}>${block.data.text}</h${block.data.level}>`
        break
      case 'list':
        const listType = block.data.style === 'ordered' ? 'ol' : 'ul'
        const items = block.data.items.map((item) => `<li>${item}</li>`).join('')
        html += `<${listType}>${items}</${listType}>`
        break
      case 'quote':
        html += `<blockquote><p>${block.data.text}</p></blockquote>`
        break
      case 'code':
        html += `<pre><code>${block.data.code}</code></pre>`
        break
      case 'image':
        html += `<img src="${block.data.file.url}" alt="${block.data.caption || ''}" />`
        break
      // Add more block types as needed
    }
  })

  return html
}

// Use converted HTML in Tiptap
const htmlContent = editorJsToHtml(editorJsData)
const editor = new Editor({
  content: htmlContent,
  extensions: [StarterKit],
})
```

If you already have HTML output from Editor.js, you can use it directly:

```ts
// Your existing Editor.js HTML content
const existingContent = '<p>Hello <strong>world</strong>!</p>'

// Use directly in Tiptap
const editor = new Editor({
  content: existingContent,
  extensions: [StarterKit],
})
```

While HTML works perfectly, we recommend converting it to Tiptap's JSON format for better performance and readability. For batch conversion of existing content, use the [HTML utility](https://tiptap.dev/docs/editor/api/utilities/html.md) to convert HTML to JSON programmatically.

## Editor setup

### Installation

First, install Tiptap and its dependencies:

```bash
npm install @tiptap/core @tiptap/starter-kit
```

Tiptap supports all modern frontend UI frameworks like React and Vue. Follow the framework-specific installation instructions in our [installation guides](https://tiptap.dev/docs/editor/getting-started/install.md).

### Basic editor setup

Replace your Editor.js initialization with Tiptap:

```ts
// Editor.js (before)
import EditorJS from '@editorjs/editorjs'
import Header from '@editorjs/header'
import List from '@editorjs/list'
import Quote from '@editorjs/quote'
import Code from '@editorjs/code'
import Image from '@editorjs/image'

const editor = new EditorJS({
  holder: 'editorjs',
  tools: {
    header: Header,
    list: List,
    quote: Quote,
    code: Code,
    image: Image,
  },
})

// Tiptap (after)
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'

const editor = new Editor({
  element: document.querySelector('#editor'),
  extensions: [StarterKit],
  content: '<p>Hello World!</p>',
})
```

## Extensions

### Understanding Tiptap's extension system

Tiptap uses a modular extension system that differs from Editor.js's tool-based approach. Instead of discrete blocks, Tiptap uses a continuous document model with extensions providing formatting and functionality.

The [StarterKit](https://tiptap.dev/docs/editor/extensions/functionality/starterkit.md) is a bundle of all the basic extensions, and you can add or remove other extensions as needed.

Explore all available extensions in our [extensions guide](https://tiptap.dev/docs/editor/extensions/overview.md), or [create your own](https://tiptap.dev/docs/editor/extensions/custom-extensions.md) to support custom functionality and HTML elements.

### Common Editor.js tool equivalents

| Editor.js Tool        | Tiptap Extension                        | Notes                  |
| --------------------- | --------------------------------------- | ---------------------- |
| `@editorjs/paragraph` | `Paragraph`                             | Included in StarterKit |
| `@editorjs/header`    | `Heading`                               | Included in StarterKit |
| `@editorjs/list`      | `BulletList`, `OrderedList`, `ListItem` | Included in StarterKit |
| `@editorjs/quote`     | `Blockquote`                            | Included in StarterKit |
| `@editorjs/code`      | `CodeBlock`                             | Included in StarterKit |
| `@editorjs/image`     | `Image`                                 | Available separately   |
| `@editorjs/table`     | `Table`                                 | Available separately   |
| `@editorjs/link`      | `Link`                                  | Included in StarterKit |
| `@editorjs/marker`    | `Highlight`                             | Available separately   |
| `@editorjs/delimiter` | `HorizontalRule`                        | Included in StarterKit |

### Extension configuration

```ts
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import Image from '@tiptap/extension-image'
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableHeader from '@tiptap/extension-table-header'
import TableCell from '@tiptap/extension-table-cell'
import Highlight from '@tiptap/extension-highlight'

const editor = new Editor({
  extensions: [
    StarterKit,
    Image.configure({
      inline: true,
      allowBase64: true,
    }),
    Table.configure({
      resizable: true,
    }),
    TableRow,
    TableHeader,
    TableCell,
    Highlight.configure({
      multicolor: true,
    }),
  ],
})
```

### Custom extensions

For Editor.js custom tools, create custom Tiptap extensions. See our [custom extensions guide](https://tiptap.dev/docs/editor/extensions/custom-extensions.md) for detailed instructions.

## UI implementation

### Toolbar implementation

Editor.js's inline toolbar can be replicated with Tiptap's toolbar components:

```tsx
// Tiptap toolbar (React example)
function Toolbar({ editor }) {
  if (!editor) return null

  return (
    <div className="toolbar">
      <button
        onClick={() => editor.chain().focus().toggleBold().run()}
        className={editor.isActive('bold') ? 'active' : ''}
      >
        Bold
      </button>
      <button
        onClick={() => editor.chain().focus().toggleItalic().run()}
        className={editor.isActive('italic') ? 'active' : ''}
      >
        Italic
      </button>
      <button
        onClick={() => editor.chain().focus().toggleUnderline().run()}
        className={editor.isActive('underline') ? 'active' : ''}
      >
        Underline
      </button>
    </div>
  )
}
```

### Pre-built UI components

For faster development, use Tiptap's pre-built UI components:

- Explore our [UI components](https://tiptap.dev/docs/ui-components/getting-started/overview.md) for ready-to-use components
- Check out practical examples in our [default text editor example](https://tiptap.dev/docs/examples/basics/default-text-editor.md)

### Inline toolbar (Editor.js style)

Replicate Editor.js's inline toolbar using Tiptap's BubbleMenu:

```tsx
import { BubbleMenu } from '@tiptap/react'

function MyEditor() {
  const editor = useEditor({
    extensions: [StarterKit],
  })

  return (
    <>
      <EditorContent editor={editor} />
      <BubbleMenu editor={editor}>
        <button
          onClick={() => editor.chain().focus().toggleBold().run()}
          className={editor.isActive('bold') ? 'active' : ''}
        >
          Bold
        </button>
        <button
          onClick={() => editor.chain().focus().toggleItalic().run()}
          className={editor.isActive('italic') ? 'active' : ''}
        >
          Italic
        </button>
      </BubbleMenu>
    </>
  )
}
```

### Block-based UI (alternative approach)

If you prefer Editor.js's block-based approach, use our [Block editor template](https://tiptap.dev/docs/ui-components/getting-started/overview.md) (coming soon) to achieve the UI of a Notion-like block-based text editor out of the box.

## Migration checklist

Install Tiptap packages
Convert Editor.js JSON content to HTML
Replace Editor.js initialization with Tiptap setup
Map Editor.js tools to Tiptap extensions
Migrate custom tools to custom extensions or [Node Views](https://tiptap.dev/docs/editor/extensions/custom-extensions/node-views.md)
Implement toolbar UI components
Test content compatibility
Convert existing content to JSON format (recommended)
Implement custom extensions for any missing functionality
Update event handlers and API calls
Test inline toolbar functionality
Verify image upload and handling
Test block-specific features (quotes, code blocks, etc.)

## Next steps

- Explore the [extension overview](https://tiptap.dev/docs/editor/extensions/overview.md) to discover all available extensions
- Learn about [custom extensions](https://tiptap.dev/docs/editor/extensions/custom-extensions.md) for advanced customization
- Check out our [examples](https://tiptap.dev/docs/examples.md) for implementation inspiration
- Review the [performance guide](https://tiptap.dev/docs/guides/performance.md) for optimization tips
