A Lexical alternative that runs without React.
Lexical is fast and extensible, but it is React-first and leaves the toolbar, theming, and collaboration to you. Rune works with any framework (or none), drives its entire UI from a config object, and ships real-time collaboration built in — with zero runtime dependencies.
Rune vs Lexical
| rune | Lexical | |
|---|---|---|
| Zero runtime dependencies | Yes | No |
| No build step required | Yes | No |
| Config-driven toolbar & menus | Yes | No — you build the UI |
| Headless / CSS-variable theming | Yes | Partial — theme via classes |
| Works without a framework | Yes | Partial — React-first |
| Real-time collaboration | Built in (Yjs) | Add-on (@lexical/yjs) |
| License | MIT | MIT |
What you gain with Rune.
- 01
Not tied to React
Lexical's first-class experience is React via @lexical/react. Rune ships first-class adapters for Vanilla JS, React, Vue, Svelte, and a Web Component from one package.
- 02
A toolbar out of the box
Lexical gives you primitives and asks you to assemble the editor UI from plugins. Rune renders a full toolbar, bubble menu, and slash menu from one config — no UI plumbing.
- 03
Collaboration in the box
Lexical collaboration means wiring @lexical/yjs yourself. Rune's collaboration layer ships with presence, comments, tracked changes, and offline persistence ready to enable.
Migrating from Lexical
Lexical requires composing several plugins around a contenteditable to get a working rich-text editor. Rune renders the equivalent — toolbar, menus, and history — from a single config object.
import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'
const initialConfig = { namespace: 'Editor', onError: console.error }
function Editor() {
return (
<LexicalComposer initialConfig={initialConfig}>
<RichTextPlugin
contentEditable={<ContentEditable />}
placeholder={<div>Enter text…</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
</LexicalComposer>
)
}import { RuneEditor } from '@parityfox/rune-editor/react'
import config from './rune.config.js'
import '@parityfox/rune-editor/styles'
export default function Editor() {
return (
<RuneEditor
extensions={config.extensions}
content="<p>Hello</p>"
onChange={(html) => console.log(html)}
/>
)
}When to choose Lexical instead
Lexical is built and maintained by Meta and runs at Facebook scale, with strong performance and accessibility. If you're committed to React and want a Meta-backed foundation with a growing plugin set, Lexical is a proven, well-supported choice.
Questions
- Can I use Rune without React?
- Yes. Unlike Lexical, Rune is framework-agnostic. It ships adapters for Vanilla JS, React, Vue 3, Svelte, and a native Web Component, all from the same package.
- Does Rune include a toolbar like Lexical's plugins?
- Rune renders the toolbar, bubble menu, and slash menu for you from a config object. With Lexical you assemble the UI from plugins yourself.
- How does collaboration compare?
- Both use Yjs. Lexical exposes a binding (@lexical/yjs) you wire up; Rune ships an opt-in collaboration layer with presence, comments, tracked changes, and offline persistence built in.
Try the framework-agnostic alternative.
Use Rune with React — or Vue, Svelte, vanilla JS, or a Web Component. Same engine, five adapters, zero dependencies.