# facebook/lexical: a plugin-based editor framework for React and vanilla JS

> Lexical is an extensible text editor framework from Meta, written in TypeScript and shipped under MIT. This review covers what it solves, how its immutable node model works, how to install it, and where it stops being the right tool.

**facebook/lexical** — Lexical is an extensible text editor framework that provides excellent reliability, accessibility and performance.

- Repository: https://github.com/facebook/lexical
- Website: https://lexical.dev
- Stars: 23,914 · Forks: 2,235
- Language: TypeScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/facebook-lexical

## The editing problem Lexical is meant to remove

Contenteditable gives you a DOM that the browser mutates in ways no framework controls. Selection ranges survive or collapse unpredictably, IME composition fights with your state updates, and undo history is whatever the browser decides it is. Most teams either accept that behaviour or write their own document model on top of it. Lexical takes the second route and ships the model for you.

The audience is narrow and specific. Lexical targets engineers who are building an editor into a React or vanilla JS application and who need control over the document tree: custom node types, a defined serialization format, or collaborative editing. The README describes it as a framework rather than a component, and that distinction matters. You get primitives, not a toolbar. If you want a drop-in WYSIWYG widget with a menu bar, this is the wrong starting point.

## How the immutable node model and plugin layer fit together

The core is framework agnostic. An editor instance holds an immutable state tree of nodes, and every change produces a new state rather than mutating the old one. That is what makes the built-in undo and redo work without extra bookkeeping, and it is also why state can be serialized to JSON. The README lists import and export for JSON, Markdown and HTML.

Plugins are the extension mechanism. Rather than subclassing an editor component, you register behaviour that listens to editor commands and node changes. The React bindings wrap this in context providers: LexicalComposer supplies the initial config, and individual plugins such as HistoryPlugin attach their behaviour inside it. Because the core does not depend on React, the same node definitions and commands can be driven from the vanilla JS entry point, and the repository carries examples for both paths.

Collaboration is not part of the core either. The README states that real-time collaboration runs through a Yjs integration, which means the CRDT layer is a separate dependency you add and configure. That is an honest separation, but it also means conflict resolution behaviour is Yjs behaviour, not Lexical behaviour, and you should evaluate them as two systems.

## Installing Lexical and rendering a first editor

For React applications the README gives a single install line covering the core package and the official bindings.

```bash
npm install lexical @lexical/react
```

After that, the smallest working editor is a composer wrapping a plain text plugin, a content editable region, an error boundary and the history plugin. The initial config needs a namespace and an error handler; the README's example uses exactly those two keys.

```jsx
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';

const initialConfig = {
  namespace: 'MyEditor',
  onError: (error) => console.error(error),
};
```

Render LexicalComposer with that config, put PlainTextPlugin inside it, and pass ContentEditable as the contentEditable prop with LexicalErrorBoundary as the ErrorBoundary prop. On screen you should get an empty editable region that accepts typing and responds to undo. Nothing else appears, because a plain text plugin has no toolbar and no formatting commands attached.

If you are not using React, the README points to the Vanilla JS quick start and the vanilla-js example rather than showing a snippet. For a working reference implementation, the repository ships examples including react-plain-text, react-rich, react-rich-collab, markdown-editor, react-table and extension-sveltekit-ssr-hydration. Each example is run from the monorepo with a script that installs its dependencies and starts its dev server, so you can read a complete setup instead of assembling one from documentation.

## Where Lexical stops being the right tool

The plugin architecture is the main cost. Everything beyond plain text is a plugin you add, order and configure: rich text, history, lists, tables, code blocks, images. The README lists these as supported content types, and they are supported, but through packages rather than through the core. A team expecting to install one package and get a finished editor will spend its first week wiring plugins.

Browser support is bounded and stated explicitly: Chrome 86+, Firefox 115+, Safari 15+ and Edge 86+. Older Safari and Firefox builds are outside that range. If your audience includes locked-down enterprise browsers or embedded webviews pinned to older engines, that constraint decides the question before any architectural comparison does.

The repository is a monorepo with a pinned toolchain. The root package.json requires Node 20.19.0 or newer and pnpm 11 or newer, and declares pnpm 11.24.0 as the package manager. Building from source, running the playground or running the test suites therefore assumes that toolchain; contributing is not a matter of cloning and running npm install. The README also does not document a rollback procedure for editor state, so if your application needs to revert a document to an earlier revision beyond the built-in undo stack, that is your own persistence layer to design.

## Lexical against ProseMirror and other editor toolkits

The obvious comparison is ProseMirror, and the difference is in the state layer. ProseMirror models a document as a schema-validated tree with transactions and steps, and it has a long-established ecosystem of schema definitions. Lexical instead exposes an immutable node tree with editor commands and a plugin registry, and it ships official React bindings rather than leaving the integration to the community. If your application is React and you want the editor to behave like a React component tree, Lexical's bindings remove integration work that ProseMirror leaves to you.

Slate is the other reference point. Slate also uses a JSON document model and is React-oriented, but its core is smaller and more permissive about what a node can be, which shifts more validation onto application code. Lexical is more prescriptive about node classes and commands, which is a constraint and a benefit: less freedom, fewer ways to produce an invalid tree.

For plain rich text with no custom nodes, a simpler embedded editor will get you to production faster than any of these. The framework route pays off only when the document structure itself is the product.

## Release cadence, upgrade cost and the MIT licence

Lexical is not archived, and the last push to the repository was on 2026-09-18. Releases arrive frequently: v0.49.0 on 2026-07-30, v0.50.0 on 2026-09-02 and v0.51.0 on 2026-09-17. The version numbers are still below 1.0, which is the practical signal for upgrade planning. Release notes live in GitHub Releases, and the repository keeps a CHANGELOG.md at the root. There is no separate long-term support line described in the README, so the upgrade path is to track releases and read the notes between the version you run and the one you move to.

Upgrading also touches the React bindings, since @lexical/react is versioned alongside the core. A change in node behaviour or command signatures can require edits in every plugin you have written, and custom nodes are the part least likely to be covered by the examples.

The licence is MIT, with the copyright line reading Meta Platforms, Inc. That permits commercial use and modification, but it is a permissive licence with no patent grant language of the kind some corporate legal teams look for. Whether that matters for your organisation is a question for your legal team, not for this review.

## Conclusion

Adopt Lexical if you are building a React or vanilla JS editor that needs custom nodes, JSON serialization or Yjs collaboration, and you accept writing plugin code yourself. Do not adopt it if you want a finished editor UI out of the box; the playground is a reference app, not a product. Before committing, verify that your target browsers are covered (Chrome 86+, Firefox 115+, Safari 15+, Edge 86+) and that the node types you need can be expressed as Lexical nodes.

## FAQ

### How do I install Lexical for a React application?

The README gives a single command: npm install lexical @lexical/react. The core package is framework agnostic and the React bindings are a separate package installed alongside it.

### What is Lexical and what does it do?

Lexical is an extensible text editor framework written in TypeScript, described in the README as providing reliability, accessibility and performance. It offers a framework agnostic core, official React bindings, a plugin architecture, an immutable state model and serialization to JSON, Markdown and HTML.

### How do I use Lexical in an application?

For React, wrap your editor in LexicalComposer with an initialConfig containing a namespace and an onError handler, then place plugins such as PlainTextPlugin and HistoryPlugin inside it. For non-React usage the README points to the Vanilla JS quick start and the vanilla-js example.

## Sources

- [facebook/lexical on GitHub](https://github.com/facebook/lexical)
- [License: MIT](https://github.com/facebook/lexical/blob/main/LICENSE)
- [Project website](https://lexical.dev)
- [README](https://github.com/facebook/lexical/blob/main/README.md)
- [Releases](https://github.com/facebook/lexical/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/facebook-lexical
