Open-source project
codex-team/editor.js avatar
codex-team/editor.js

Editor.js: a block editor that stores content as JSON instead of HTML

A block-style editor with clean JSON output

31,968 stars2,249 forksTypeScriptApache-2.0

At a glance

What is it?
Editor.js is a TypeScript block editor whose saved output is a JSON document rather than markup. This review covers its installation, the block and tool model, the plugin ecosystem, and where the JSON-first design becomes a cost.
Who is it for?
Adopt Editor.js if your pipeline stores structured content and you are willing to assemble and maintain a tool set: the JSON output is the reason to pick it over a markup editor. Skip it if you need collaborative editing today, because the roadmap still lists the operations manager, undo/redo manager and server communication as unchecked items, or if you want a batteries-included editor with tables, images and embeds already wired up.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 13 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Editor.js solves: content that is data, not markup

Most WYSIWYG editors hand you an HTML string. That string then has to be sanitized before storage, parsed again when you render it on iOS or Android, and patched whenever the editor changes its tag structure. Editor.js takes a different position. The README states that the editor outputs clean JSON data instead of heavy HTML markup, and lists Web, iOS, Android, AMP, Instant Articles, speech readers and AI chatbots as places that output can be consumed. That is the whole pitch, and it is a real one: a block list of typed objects is easier to validate, migrate and re-render than a fragment of HTML.

The audience follows from that. If your product stores articles, documentation, course material or CMS entries and you control the rendering layer, a typed document is a better contract than markup. If your requirement is to paste formatted HTML from Word into a field and store the result, Editor.js is aimed at the wrong problem. The README positions it as a block-style interface where text, images, lists and quotes are separate blocks, and each block type arrives as a separate plugin. The core package is the editor shell; the content types are yours to choose.

How the block and tool model actually works

An Editor.js instance is constructed with a configuration object whose tools key maps tool names to tool classes or packages. The core renders a container, manages the block list, handles the caret and the toolbars, and delegates rendering and data extraction for each block to the tool that owns it. The README's initialization example is a div with id editorjs and a new EditorJS call that passes a tools object, with the comment that you supply your own tools.

Saving is explicit. The README instructs you to call editor.save() and handle the returned Promise with the saved data, shown as const data = await editor.save(). That Promise resolves to the document: a structure of blocks, each carrying a type and its own data payload defined by the tool that produced it. Nothing in the core decides what a paragraph or a table looks like on the wire; the tool does. This is why the output stays clean and also why it is not portable between tool versions without care.

The repository layout reflects the split. src/ holds the core in TypeScript, types/ ships the declaration file referenced by the types field in package.json, and example/ contains several standalone pages: example.html, example-i18n.html, example-multiple.html, example-popup.html and example-rtl.html. Those files are the fastest way to see the API in use, including multiple editor instances and right-to-left layout, which the README does not explain in prose.

Installing Editor.js and saving your first document

The README gives a three-step path: install Editor.js, install the tools you need, initialize the instance. Installation is a single npm package, and the README also points to a CDN build on jsDelivr for the same package. Run the install command in your project root.

bash
npm i @editorjs/editorjs

The package is published as @editorjs/editorjs, currently at version 2.31.6 according to package.json. Next, pick tools. The README links a list that includes Heading, Quote, Image, Simple Image, Nested List, Checklist, Link embed, Embeds, Table, Delimiter, Warning, Code, Raw HTML, Attaches, Marker and Inline Code, and points to the Awesome Editor.js list for more. Two of them are worth noting for their constraints: Simple Image is described as working without a backend requirement, while Image is not, which matters if you have no upload endpoint.

Then mount the editor on a container element and pass the tools you installed. The README shows the container and the constructor.

html
<div id="editorjs"></div>
javascript
import EditorJS from '@editorjs/editorjs'

const editor = new EditorJS({
  tools: {
   // ... your tools
  }
})

After the user edits, call save and await the Promise. The README's example is two lines, and what you get back is the JSON document to post to your API.

javascript
const data = await editor.save()

For a working reference beyond the snippet, open example/example.html in the repository, which the README calls out as the place to view more detailed examples. If you want to run the repository itself, package.json defines dev as vite and build as vite build --mode production.

Where the plugin-per-block design costs you

The flexibility is also the maintenance burden. Every block type you want is a dependency you install, version, style and keep compatible with the core. The README's own list of tools is a list of separate GitHub repositories, each with its own release cadence. A heading tool and an image tool can drift apart in the data they emit, and the core will not reconcile that for you. Teams used to a single package with a built-in toolbar of twenty features will find the assembly work front-loaded and ongoing.

Collaborative editing is not there yet. The roadmap in the README lists collaborative editing with unchecked boxes for the Inline Tools JSON format, the Operations Observer, Executor, Manager and Transformer, the Undo/Redo Manager, Tools API changes, server and communication, and updating the basic tools to the new API. Undo/redo sits inside that unfinished group. If your requirement is two cursors in one document, or reliable undo across blocks, the README does not claim either is ready.

The output being JSON also means you own rendering. There is no server-side HTML renderer in the core package described here; if you need to serve the document as HTML for SEO or email, you write that mapping yourself, and you write it again for each new block type you add. That is the trade the README makes when it says the data is easy to sanitize and extend with your logic. Sanitizing is easier. Rendering is now your job.

Editor.js compared with Tiptap and Quill

The related searches around this project are mostly comparisons, and the honest difference is architectural rather than cosmetic. Tiptap and Quill are ProseMirror-derived or document-model editors: the content is a rich document tree that can be serialized to HTML, JSON or Markdown, and the editing surface behaves like a continuous text field with inline marks. Editor.js inverts that. There is no single document model to serialize; there is a list of blocks, and each block's schema belongs to its tool. Inline formatting inside a block is the tool's business, and the roadmap item about implementing the Inline Tools JSON format suggests that part is still being settled.

The practical consequence is what you get for free. With a document-model editor you tend to get HTML output, a mature schema, and collaboration support from the surrounding ecosystem. With Editor.js you get a block list that maps cleanly onto a database row per block and a UI that makes non-text content first-class. If your content is mostly prose with occasional embeds, the block model adds ceremony. If your content is a mix of text, images, tables and warnings that you want to query and reorder individually, the block list is the more natural shape.

Markdown is a related search worth addressing directly. Editor.js does not store Markdown. Its saved document is JSON, and any Markdown you want is a conversion you write against the block types you chose. That is a different proposition from editors that treat Markdown as a first-class input format.

Maintenance, licence and what you are signing up for

The repository is not archived, and the last push was on 2026-08-31. Recent releases are v2.31.6 on 2026-04-07, v2.31.5 on 2026-03-11 and v2.31.4 on 2026-03-04, so the core has a release history through this year. The default branch is next, not main or master, which matters when you pin a dependency or read source on GitHub: the README's changelog link points at the next branch.

Upgrade cost is dominated by the tools, not the core. The core version in package.json is 2.31.6 and it ships TypeScript types through the types field, so type errors will surface at build time rather than at runtime when a tool's data shape changes. The repository tests the core with Cypress end-to-end specs: package.json defines test:e2e as a test build followed by cypress run, and test:e2e:open for the interactive runner. Those specs cover the core, not the third-party tools you add.

The licence is Apache-2.0, stated in both the README's package metadata and the LICENSE file at the repository root. Apache-2.0 is a permissive licence with an explicit patent grant and a notice requirement when you redistribute. It does not oblige you to publish your own application code. That is a statement about the licence text, not legal advice; if you are redistributing the editor inside a product, have your own counsel read the NOTICE and modification clauses.

The project asks for money. The README has a donation section with OpenCollective, crypto and Patreon links, and argues that businesses relying on Editor.js should want it maintained. That is a fair ask for a project whose core is free, but it also tells you the maintenance model: sponsorship, not a paid support contract.

Editorial conclusion

Adopt Editor.js if your pipeline stores structured content and you are willing to assemble and maintain a tool set: the JSON output is the reason to pick it over a markup editor. Skip it if you need collaborative editing today, because the roadmap still lists the operations manager, undo/redo manager and server communication as unchecked items, or if you want a batteries-included editor with tables, images and embeds already wired up. Before committing, open example/example.html in the repository, install @editorjs/editorjs at version 2.31.6, and confirm that editor.save() returns the block shape your backend expects.

Frequently asked questions

How do I install Editor.js?

Install the core package with npm i @editorjs/editorjs, then install the tools you need as separate packages. The README also points to a CDN build on jsDelivr if you are not using a bundler. After that you mount the editor on a container element and pass your tools in the constructor.

How do I use Editor.js in React?

The README does not document a React wrapper. Its initialization example is plain JavaScript: an element with id editorjs and a new EditorJS call with a tools object, followed by editor.save() to read the document. In React you would create the container in a ref and construct the instance in an effect, but that wiring is not in the README.

What is Editor.js?

It is an open-source block-style editor written in TypeScript that outputs a JSON document instead of HTML markup. Each block type, such as a heading, image or list, is supplied by a separate plugin, so the editor core stays small and you choose the content types.

Is Editor.js free?

Yes. The README lists it as free and open source, and the package metadata and LICENSE file give the licence as Apache-2.0, which permits commercial use. The project does ask for donations through OpenCollective, crypto and Patreon.

How does Editor.js differ from Quill or Tiptap?

Editor.js stores a list of typed blocks and delegates each block's data shape to its tool, while Quill and Tiptap are document-model editors that typically serialize to HTML or a document tree. The README's roadmap still lists collaborative editing items as unfinished, so that is not a reason to choose Editor.js today.

Official sources

  1. codex-team/editor.js on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/codex-team-editor-js.svg)](https://hysenlabs.com/projects/codex-team-editor-js)