A modern rich text editor for Rails

The Trix document model

Document
Block Hello world
Block quote A quoted line
Block quotebulletListbullet A bullet inside the quote
Block bulletListbullet Another bullet

A flat list of blocks with very limited extensibility options

Sep 2022 Tables hit Trix’s ceiling

Brian Bailey“Think HTML tables… with a visual editor” — Brian

Apr 2023 Tiptap spike in HEY

David Heinemeier Hansson“I’d be happy for us to spend a cycle to see if we could get real with tiptap” — David

Mar 2024 House for Writebook

Kevin McConnell“Nearly a textarea, but with some basic styles on top” — Kevin

Feb 2025 Doubts about House in other products

Jorge Manrubia“Are we aiming to go in a more WYSIWYG direction in general?” — Jorge

Apr 2025 Editors discussion

Brian Bailey“I’m not sure either editor is our long-term future” — Brian

David Heinemeier Hansson“No interest in being at the mercy of a VC pivot” — David on Tiptap

Jorge Manrubia“Lexical from Meta is MIT and looks quite powerful” — Jorge

Apr 2025 A new editor for Fizzy

Brian Bailey“If we pull it off, we’ll launch Fizzy with a fabulous writing environment and lay the groundwork for bringing it to HEY and Basecamp in the future” — Brian

May 2025 Lexxy is born

Jorge Manrubia“Lexical is a solid bet. I didn’t find any blocker or deterrent” — Jorge

A tiny core. Pick the rest. @lexical/rich-text @lexical/plain-text @lexical/history @lexical/list @lexical/link @lexical/table @lexical/code @lexical/markdown @lexical/selection @lexical/clipboard @lexical/html @lexical/utils @lexical/extension Immutable editor state contenteditable I/O Commands Node transforms DOM reconciler lexical 0 deps · 42 KB · MIT

At Meta, Lexical powers web text editing experiences for hundreds of millions of users everyday across Facebook, Workplace, Messenger, WhatsApp and Instagram.

lexical.dev/docs/intro

Pick Lexical

Wire it up

Add a toolbar

What you envision Reality Captions Links Sanitization Selection & caret Galleries Toolbar Trix compatibility Turbo morphing Android keyboards Attachments & uploads Nested lists Code highlighting Safari UI for tables Performance Accessibility Paste handling Plain-text mode Mentions Native apps Color highlighting Action Text adapter Drag & drop Keyboard shortcuts Markdown Clean HTML Docs & sandbox Undo Dark mode Emoji

Pick Lexical

Wire it up

Add a toolbar

May 2025 First PR
Dec 2025 Fizzy 🚀
Zoltán Hosszú
Zoltán Hosszú
Samuel Péchèr
Samuel Péchèr
May 2026 Basecamp 5 🚀

Not good. Very good.

Color highlighter
Tables
Markdown
Code highlighting
Image galleries
Configurable prompts
Paste URLs
Attachment previews

Action Text native

Lexxy with a line of text and a photo

<p>Lago di Braies, last summer</p>
<action-text-attachment
  sgid="demo-sgid-1"
  url="/rails/active_storage/blobs/demo-signed-id-1/braies-lake.jpg"
  alt="braies-lake.jpg"
  caption=""
  content-type="image/jpeg"
  filename="braies-lake.jpg"
  filesize="346211"
  presentation="gallery"
></action-text-attachment>
            
Action Text rich_textarea :body Editor adapter ActionText::Editor Trix TrixEditor Lexxy LexxyEditor

config.action_text.editor = :lexxy
          

Extendable


class MyExtension extends Lexxy.Extension {
  get enabled() { … }

  get allowedElements() { … }

  get lexicalExtension() {
    return this.defineExtension({
      name: "my-extension",
      nodes: [ … ],
      register(editor) { … }
    })
  }

  initializeToolbar(toolbar) { … }

  dispose() { … }
}

Lexxy.configure({ global: { extensions: [ MyExtension ] } })
          
Voice notes in Basecamp

Milliseconds per keystroke

Trix Lexxy

Accessibility

Bruno Prieto
Bruno Prieto
Michael Berger
Michael Berger
<lexxy-toolbar role="toolbar">
  <button title="Bold" aria-pressed="false">
  <button title="Color highlight" aria-haspopup="menu">
  <div role="menu" aria-label="Color highlight">
    <div role="group" aria-label="Text color">
      <button role="menuitemcheckbox" aria-label="Yellow">

<div contenteditable role="textbox" aria-multiline="true">
  <figure class="attachment">
    <span class="lexxy-fake-selection">
      Lago di Braies
    <textarea aria-label="Image caption">

<lexxy-attachment-toolbar role="toolbar">
  <button aria-label="Remove">

<span aria-live="assertive">
Lexxy with a photo attachment selected and its Remove control
  • AltF10 toolbars
  • Esc back to the text
  • AltShift↑↓ move attachments
  • Voice dictation with Dragon

Security

Jeremy Daer
Jeremy Daer
Mike Dalessio
Mike Dalessio

Lexxy ❤️ Agents

Browser tests

Cards closed per day Commits per day (avg)

275 cards closed

1.0

The new Rails default