How would you build a rich text editor (like Medium) in React?

Design a minimal Medium-style rich text editor with contentEditable, commands, history, block/inline formats, selection APIs, and plugins.

advancedUi patternsreactrich text editorcontentEditabletext formatting
Published: 11/23/2025
Updated: 11/23/2025

Advertisement

đź§© Scenario

You want to create a lightweight Medium-like editor that supports:

  • Bold / Italic / Underline / Code formatting
  • Headings, paragraphs, quotes
  • Inline links
  • Undo / Redo
  • Keyboard shortcuts (Cmd+B, Cmd+I)
  • Persisting content

This must work without external heavy libraries.


đź§  Answer (Design Overview)

1. Approach Options

A. contentEditable-based editor

  • Easiest to start
  • Browser handles selection
  • Use commands + manual formatting

B. Custom editor engine (Slate/Lexical/ProseMirror)

  • More stable for complex editors
  • Schema-based content
  • Better for collaboration, comments, plugins

For this scenario, we focus on contentEditable.


2. Core Architecture

State Representation

Use HTML or JSON:

{
  type: 'doc',
  blocks: [
    { type: 'paragraph', children: [{ text: 'Hello' }] }
  ]
}

Selection Handling

Use window.getSelection() to get ranges and apply commands.

Formatting Commands

Use document.execCommand() (deprecated but widely supported) or apply manual format wrapping using Range API.

Undo / Redo

Keep history:

history = [html1, html2, html3];
index = current;

🎮 Live Demo: Rich Text Editor (Medium-style)


🔍 Real-World Tips

  • Use Normalization to ensure consistent HTML output.
  • Use keyboard handlers for shortcuts.
  • Add paste sanitization to clean HTML.
  • For serious editors, move to Lexical or Slate for plugin systems.
  • For collaboration (Google Docs style), use CRDTs (Yjs, Automerge).

Quick Practice

  1. Add support for headings using custom commands.
  2. Implement inline link creation.
  3. Add paste sanitization.
  4. Add markdown shortcuts (typing ## becomes <h2>).

Summary

  • contentEditable is the easiest way to build a minimal editor.
  • Keep HTML or JSON as the canonical state.
  • Implement formatting with execCommand or Range API.
  • Use history stacks for undo/redo.
Frequently Asked Questions

Should I use contentEditable or a custom editor engine?

contentEditable is great for simple editors. For advanced features (collaboration, plugins, schema), use Slate/ProseMirror/Lexical.

How do you handle undo/redo?

Track snapshots of document state or use command-based history stacks.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement